1 #include <algorithm>
2 #include <array>
3 #include <string.h>
4
5 extern "C"
6 {
7 #include "ext/libkirk/kirk_engine.h"
8 #include "ext/libkirk/SHA1.h"
9 }
10 #include "Common/Common.h"
11 #include "Common/Log.h"
12 #include "Common/Swap.h"
13 #include "Core/ELF/PrxDecrypter.h"
14
15 #define ROUNDUP16(x) (((x)+15)&~15)
16
17 // Thank you PSARDUMPER & JPCSP keys
18
19 // PRXDecrypter 16-byte tag keys.
20 static const u8 keys260_0[] = {0xC3, 0x24, 0x89, 0xD3, 0x80, 0x87, 0xB2, 0x4E, 0x4C, 0xD7, 0x49, 0xE4, 0x9D, 0x1D, 0x34, 0xD1};
21 static const u8 keys260_1[] = {0xF3, 0xAC, 0x6E, 0x7C, 0x04, 0x0A, 0x23, 0xE7, 0x0D, 0x33, 0xD8, 0x24, 0x73, 0x39, 0x2B, 0x4A};
22 static const u8 keys260_2[] = {0x72, 0xB4, 0x39, 0xFF, 0x34, 0x9B, 0xAE, 0x82, 0x30, 0x34, 0x4A, 0x1D, 0xA2, 0xD8, 0xB4, 0x3C};
23 static const u8 keys280_0[] = {0xCA, 0xFB, 0xBF, 0xC7, 0x50, 0xEA, 0xB4, 0x40, 0x8E, 0x44, 0x5C, 0x63, 0x53, 0xCE, 0x80, 0xB1};
24 static const u8 keys280_1[] = {0x40, 0x9B, 0xC6, 0x9B, 0xA9, 0xFB, 0x84, 0x7F, 0x72, 0x21, 0xD2, 0x36, 0x96, 0x55, 0x09, 0x74};
25 static const u8 keys280_2[] = {0x03, 0xA7, 0xCC, 0x4A, 0x5B, 0x91, 0xC2, 0x07, 0xFF, 0xFC, 0x26, 0x25, 0x1E, 0x42, 0x4B, 0xB5};
26 static const u8 keys300_0[] = {0x9F, 0x67, 0x1A, 0x7A, 0x22, 0xF3, 0x59, 0x0B, 0xAA, 0x6D, 0xA4, 0xC6, 0x8B, 0xD0, 0x03, 0x77};
27 static const u8 keys300_1[] = {0x15, 0x07, 0x63, 0x26, 0xDB, 0xE2, 0x69, 0x34, 0x56, 0x08, 0x2A, 0x93, 0x4E, 0x4B, 0x8A, 0xB2};
28 static const u8 keys300_2[] = {0x56, 0x3B, 0x69, 0xF7, 0x29, 0x88, 0x2F, 0x4C, 0xDB, 0xD5, 0xDE, 0x80, 0xC6, 0x5C, 0xC8, 0x73};
29 static const u8 keys303_0[] = {0x7b, 0xa1, 0xe2, 0x5a, 0x91, 0xb9, 0xd3, 0x13, 0x77, 0x65, 0x4a, 0xb7, 0xc2, 0x8a, 0x10, 0xaf};
30 static const u8 keys310_0[] = {0xa2, 0x41, 0xe8, 0x39, 0x66, 0x5b, 0xfa, 0xbb, 0x1b, 0x2d, 0x6e, 0x0e, 0x33, 0xe5, 0xd7, 0x3f};
31 static const u8 keys310_1[] = {0xA4, 0x60, 0x8F, 0xAB, 0xAB, 0xDE, 0xA5, 0x65, 0x5D, 0x43, 0x3A, 0xD1, 0x5E, 0xC3, 0xFF, 0xEA};
32 static const u8 keys310_2[] = {0xE7, 0x5C, 0x85, 0x7A, 0x59, 0xB4, 0xE3, 0x1D, 0xD0, 0x9E, 0xCE, 0xC2, 0xD6, 0xD4, 0xBD, 0x2B};
33 static const u8 keys310_3[] = {0x2E, 0x00, 0xF6, 0xF7, 0x52, 0xCF, 0x95, 0x5A, 0xA1, 0x26, 0xB4, 0x84, 0x9B, 0x58, 0x76, 0x2F};
34 static const u8 keys330_0[] = {0x3B, 0x9B, 0x1A, 0x56, 0x21, 0x80, 0x14, 0xED, 0x8E, 0x8B, 0x08, 0x42, 0xFA, 0x2C, 0xDC, 0x3A};
35 static const u8 keys330_1[] = {0xE8, 0xBE, 0x2F, 0x06, 0xB1, 0x05, 0x2A, 0xB9, 0x18, 0x18, 0x03, 0xE3, 0xEB, 0x64, 0x7D, 0x26};
36 static const u8 keys330_2[] = {0xAB, 0x82, 0x25, 0xD7, 0x43, 0x6F, 0x6C, 0xC1, 0x95, 0xC5, 0xF7, 0xF0, 0x63, 0x73, 0x3F, 0xE7};
37 static const u8 keys330_3[] = {0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F, 0x38, 0x4C, 0x4D, 0x96, 0xBD, 0x49, 0xEC, 0x9B};
38 static const u8 keys330_4[] = {0xEC, 0x3B, 0xD2, 0xC0, 0xFA, 0xC1, 0xEE, 0xB9, 0x9A, 0xBC, 0xFF, 0xA3, 0x89, 0xF2, 0x60, 0x1F};
39 static const u8 keys360_0[] = {0x3C, 0x2B, 0x51, 0xD4, 0x2D, 0x85, 0x47, 0xDA, 0x2D, 0xCA, 0x18, 0xDF, 0xFE, 0x54, 0x09, 0xED};
40 static const u8 keys360_1[] = {0x31, 0x1F, 0x98, 0xD5, 0x7B, 0x58, 0x95, 0x45, 0x32, 0xAB, 0x3A, 0xE3, 0x89, 0x32, 0x4B, 0x34};
41 static const u8 keys370_0[] = {0x26, 0x38, 0x0A, 0xAC, 0xA5, 0xD8, 0x74, 0xD1, 0x32, 0xB7, 0x2A, 0xBF, 0x79, 0x9E, 0x6D, 0xDB};
42 static const u8 keys370_1[] = {0x53, 0xE7, 0xAB, 0xB9, 0xC6, 0x4A, 0x4B, 0x77, 0x92, 0x17, 0xB5, 0x74, 0x0A, 0xDA, 0xA9, 0xEA};
43 static const u8 keys370_2[] = {0x71, 0x10, 0xF0, 0xA4, 0x16, 0x14, 0xD5, 0x93, 0x12, 0xFF, 0x74, 0x96, 0xDF, 0x1F, 0xDA, 0x89};
44 static const u8 keys390_0[] = {0x45, 0xEF, 0x5C, 0x5D, 0xED, 0x81, 0x99, 0x84, 0x12, 0x94, 0x8F, 0xAB, 0xE8, 0x05, 0x6D, 0x7D};
45 static const u8 keys390_1[] = {0x70, 0x1B, 0x08, 0x25, 0x22, 0xA1, 0x4D, 0x3B, 0x69, 0x21, 0xF9, 0x71, 0x0A, 0xA8, 0x41, 0xA9};
46 static const u8 keys500_0[] = {0xEB, 0x1B, 0x53, 0x0B, 0x62, 0x49, 0x32, 0x58, 0x1F, 0x83, 0x0A, 0xF4, 0x99, 0x3D, 0x75, 0xD0};
47 static const u8 keys500_1[] = {0xBA, 0xE2, 0xA3, 0x12, 0x07, 0xFF, 0x04, 0x1B, 0x64, 0xA5, 0x11, 0x85, 0xF7, 0x2F, 0x99, 0x5B};
48 static const u8 keys500_2[] = {0x2C, 0x8E, 0xAF, 0x1D, 0xFF, 0x79, 0x73, 0x1A, 0xAD, 0x96, 0xAB, 0x09, 0xEA, 0x35, 0x59, 0x8B};
49 static const u8 keys500_c[] = {0xA3, 0x5D, 0x51, 0xE6, 0x56, 0xC8, 0x01, 0xCA, 0xE3, 0x77, 0xBF, 0xCD, 0xFF, 0x24, 0xDA, 0x4D};
50 static const u8 keys505_a[] = {0x7B, 0x94, 0x72, 0x27, 0x4C, 0xCC, 0x54, 0x3B, 0xAE, 0xDF, 0x46, 0x37, 0xAC, 0x01, 0x4D, 0x87};
51 static const u8 keys505_0[] = {0x2E, 0x8E, 0x97, 0xA2, 0x85, 0x42, 0x70, 0x73, 0x18, 0xDA, 0xA0, 0x8A, 0xF8, 0x62, 0xA2, 0xB0};
52 static const u8 keys505_1[] = {0x58, 0x2A, 0x4C, 0x69, 0x19, 0x7B, 0x83, 0x3D, 0xD2, 0x61, 0x61, 0xFE, 0x14, 0xEE, 0xAA, 0x11};
53 static const u8 keys570_5k[] = {0x6D, 0x72, 0xA4, 0xBA, 0x7F, 0xBF, 0xD1, 0xF1, 0xA9, 0xF3, 0xBB, 0x07, 0x1B, 0xC0, 0xB3, 0x66};
54 static const u8 keys600_1[] = {0xE3, 0x52, 0x39, 0x97, 0x3B, 0x84, 0x41, 0x1C, 0xC3, 0x23, 0xF1, 0xB8, 0xA9, 0x09, 0x4B, 0xF0};
55 static const u8 keys600_2[] = {0xE1, 0x45, 0x93, 0x2C, 0x53, 0xE2, 0xAB, 0x06, 0x6F, 0xB6, 0x8F, 0x0B, 0x66, 0x91, 0xE7, 0x1E};
56 static const u8 keys620_0[] = {0xD6, 0xBD, 0xCE, 0x1E, 0x12, 0xAF, 0x9A, 0xE6, 0x69, 0x30, 0xDE, 0xDA, 0x88, 0xB8, 0xFF, 0xFB};
57 static const u8 keys620_1[] = {0x1D, 0x13, 0xE9, 0x50, 0x04, 0x73, 0x3D, 0xD2, 0xE1, 0xDA, 0xB9, 0xC1, 0xE6, 0x7B, 0x25, 0xA7};
58 static const u8 keys620_a[] = {0xAC, 0x34, 0xBA, 0xB1, 0x97, 0x8D, 0xAE, 0x6F, 0xBA, 0xE8, 0xB1, 0xD6, 0xDF, 0xDF, 0xF1, 0xA2};
59 static const u8 keys620_e[] = {0xB1, 0xB3, 0x7F, 0x76, 0xC3, 0xFB, 0x88, 0xE6, 0xF8, 0x60, 0xD3, 0x35, 0x3C, 0xA3, 0x4E, 0xF3};
60 static const u8 keys620_5[] = {0xF1, 0xBC, 0x17, 0x07, 0xAE, 0xB7, 0xC8, 0x30, 0xD8, 0x34, 0x9D, 0x40, 0x6A, 0x8E, 0xDF, 0x4E};
61 static const u8 keys620_5k[] = {0x41, 0x8A, 0x35, 0x4F, 0x69, 0x3A, 0xDF, 0x04, 0xFD, 0x39, 0x46, 0xA2, 0x5C, 0x2D, 0xF2, 0x21};
62 static const u8 keys620_5v[] = {0xF2, 0x8F, 0x75, 0xA7, 0x31, 0x91, 0xCE, 0x9E, 0x75, 0xBD, 0x27, 0x26, 0xB4, 0xB4, 0x0C, 0x32};
63 static const u8 keys630_k1[] = {0x36, 0xB0, 0xDC, 0xFC, 0x59, 0x2A, 0x95, 0x1D, 0x80, 0x2D, 0x80, 0x3F, 0xCD, 0x30, 0xA0, 0x1B};
64 static const u8 keys630_k2[] = {0xd4, 0x35, 0x18, 0x02, 0x29, 0x68, 0xfb, 0xa0, 0x6a, 0xa9, 0xa5, 0xed, 0x78, 0xfd, 0x2e, 0x9d};
65 static const u8 keys630_k3[] = {0x23, 0x8D, 0x3D, 0xAE, 0x41, 0x50, 0xA0, 0xFA, 0xF3, 0x2F, 0x32, 0xCE, 0xC7, 0x27, 0xCD, 0x50};
66 static const u8 keys630_k4[] = {0xAA, 0xA1, 0xB5, 0x7C, 0x93, 0x5A, 0x95, 0xBD, 0xEF, 0x69, 0x16, 0xFC, 0x2B, 0x92, 0x31, 0xDD};
67 static const u8 keys630_k5[] = {0x87, 0x37, 0x21, 0xCC, 0x65, 0xAE, 0xAA, 0x5F, 0x40, 0xF6, 0x6F, 0x2A, 0x86, 0xC7, 0xA1, 0xC8};
68 static const u8 keys630_k6[] = {0x8D, 0xDB, 0xDC, 0x5C, 0xF2, 0x70, 0x2B, 0x40, 0xB2, 0x3D, 0x00, 0x09, 0x61, 0x7C, 0x10, 0x60};
69 static const u8 keys630_k7[] = {0x77, 0x1C, 0x06, 0x5F, 0x53, 0xEC, 0x3F, 0xFC, 0x22, 0xCE, 0x5A, 0x27, 0xFF, 0x78, 0xA8, 0x48};
70 static const u8 keys630_k8[] = {0x81, 0xD1, 0x12, 0x89, 0x35, 0xC8, 0xEA, 0x8B, 0xE0, 0x02, 0x2D, 0x2D, 0x6A, 0x18, 0x67, 0xB8};
71 static const u8 keys636_k1[] = {0x07, 0xE3, 0x08, 0x64, 0x7F, 0x60, 0xA3, 0x36, 0x6A, 0x76, 0x21, 0x44, 0xC9, 0xD7, 0x06, 0x83};
72 static const u8 keys636_k2[] = {0x91, 0xF2, 0x02, 0x9E, 0x63, 0x32, 0x30, 0xA9, 0x1D, 0xDA, 0x0B, 0xA8, 0xB7, 0x41, 0xA3, 0xCC};
73 static const u8 keys638_k4[] = {0x98, 0x43, 0xFF, 0x85, 0x68, 0xB2, 0xDB, 0x3B, 0xD4, 0x22, 0xD0, 0x4F, 0xAB, 0x5F, 0x0A, 0x31};
74 static const u8 keys639_k3[] = {0x01, 0x7B, 0xF0, 0xE9, 0xBE, 0x9A, 0xDD, 0x54, 0x37, 0xEA, 0x0E, 0xC4, 0xD6, 0x4D, 0x8E, 0x9E};
75 static const u8 keys660_k1[] = {0x76, 0xF2, 0x6C, 0x0A, 0xCA, 0x3A, 0xBA, 0x4E, 0xAC, 0x76, 0xD2, 0x40, 0xF5, 0xC3, 0xBF, 0xF9};
76 static const u8 keys660_k2[] = {0x7A, 0x3E, 0x55, 0x75, 0xB9, 0x6A, 0xFC, 0x4F, 0x3E, 0xE3, 0xDF, 0xB3, 0x6C, 0xE8, 0x2A, 0x82};
77 static const u8 keys660_k3[] = {0xFA, 0x79, 0x09, 0x36, 0xE6, 0x19, 0xE8, 0xA4, 0xA9, 0x41, 0x37, 0x18, 0x81, 0x02, 0xE9, 0xB3};
78 static const u8 keys660_v1[] = {0xBA, 0x76, 0x61, 0x47, 0x8B, 0x55, 0xA8, 0x72, 0x89, 0x15, 0x79, 0x6D, 0xD7, 0x2F, 0x78, 0x0E};
79 static const u8 keys660_v2[] = {0xF9, 0x4A, 0x6B, 0x96, 0x79, 0x3F, 0xEE, 0x0A, 0x04, 0xC8, 0x8D, 0x7E, 0x5F, 0x38, 0x3A, 0xCF};
80 static const u8 keys660_v3[] = {0x88, 0xAF, 0x18, 0xE9, 0xC3, 0xAA, 0x6B, 0x56, 0xF7, 0xC5, 0xA8, 0xBF, 0x1A, 0x84, 0xE9, 0xF3};
81 static const u8 keys660_v4[] = {0xD1, 0xB0, 0xAE, 0xC3, 0x24, 0x36, 0x13, 0x49, 0xD6, 0x49, 0xD7, 0x88, 0xEA, 0xA4, 0x99, 0x86};
82 static const u8 keys660_v5[] = {0xCB, 0x93, 0x12, 0x38, 0x31, 0xC0, 0x2D, 0x2E, 0x7A, 0x18, 0x5C, 0xAC, 0x92, 0x93, 0xAB, 0x32};
83 static const u8 keys660_v6[] = {0x92, 0x8C, 0xA4, 0x12, 0xD6, 0x5C, 0x55, 0x31, 0x5B, 0x94, 0x23, 0x9B, 0x62, 0xB3, 0xDB, 0x47};
84 static const u8 keys660_k4[] = {0xC8, 0xA0, 0x70, 0x98, 0xAE, 0xE6, 0x2B, 0x80, 0xD7, 0x91, 0xE6, 0xCA, 0x4C, 0xA9, 0x78, 0x4E};
85 static const u8 keys660_k5[] = {0xBF, 0xF8, 0x34, 0x02, 0x84, 0x47, 0xBD, 0x87, 0x1C, 0x52, 0x03, 0x23, 0x79, 0xBB, 0x59, 0x81};
86 static const u8 keys660_k6[] = {0xD2, 0x83, 0xCC, 0x63, 0xBB, 0x10, 0x15, 0xE7, 0x7B, 0xC0, 0x6D, 0xEE, 0x34, 0x9E, 0x4A, 0xFA};
87 static const u8 keys660_k7[] = {0xEB, 0xD9, 0x1E, 0x05, 0x3C, 0xAE, 0xAB, 0x62, 0xE3, 0xB7, 0x1F, 0x37, 0xE5, 0xCD, 0x68, 0xC3};
88 static const u8 keys660_v7[] = {0xC5, 0x9C, 0x77, 0x9C, 0x41, 0x01, 0xE4, 0x85, 0x79, 0xC8, 0x71, 0x63, 0xA5, 0x7D, 0x4F, 0xFB};
89 static const u8 keys660_v8[] = {0x86, 0xA0, 0x7D, 0x4D, 0xB3, 0x6B, 0xA2, 0xFD, 0xF4, 0x15, 0x85, 0x70, 0x2D, 0x6A, 0x0D, 0x3A};
90 static const u8 keys660_k8[] = {0x85, 0x93, 0x1F, 0xED, 0x2C, 0x4D, 0xA4, 0x53, 0x59, 0x9C, 0x3F, 0x16, 0xF3, 0x50, 0xDE, 0x46};
91 static const u8 key_21C0[] = {0x6A, 0x19, 0x71, 0xF3, 0x18, 0xDE, 0xD3, 0xA2, 0x6D, 0x3B, 0xDE, 0xC7, 0xBE, 0x98, 0xE2, 0x4C};
92 static const u8 key_2250[] = {0x50, 0xCC, 0x03, 0xAC, 0x3F, 0x53, 0x1A, 0xFA, 0x0A, 0xA4, 0x34, 0x23, 0x86, 0x61, 0x7F, 0x97};
93 static const u8 key_22E0[] = {0x66, 0x0F, 0xCB, 0x3B, 0x30, 0x75, 0xE3, 0x10, 0x0A, 0x95, 0x65, 0xC7, 0x3C, 0x93, 0x87, 0x22};
94 static const u8 key_2D80[] = {0x40, 0x02, 0xC0, 0xBF, 0x20, 0x02, 0xC0, 0xBF, 0x5C, 0x68, 0x2B, 0x95, 0x5F, 0x40, 0x7B, 0xB8};
95 static const u8 key_2D90[] = {0x55, 0x19, 0x35, 0x10, 0x48, 0xD8, 0x2E, 0x46, 0xA8, 0xB1, 0x47, 0x77, 0xDC, 0x49, 0x6A, 0x6F};
96 static const u8 key_2DA8[] = {0x80, 0x02, 0xC0, 0xBF, 0x00, 0x0A, 0xC0, 0xBF, 0x40, 0x03, 0xC0, 0xBF, 0x40, 0x00, 0x00, 0x00};
97 static const u8 key_2DB8[] = {0x4C, 0x2D, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xB8, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
98 static const u8 key_D91605F0[] = {0xB8, 0x8C, 0x45, 0x8B, 0xB6, 0xE7, 0x6E, 0xB8, 0x51, 0x59, 0xA6, 0x53, 0x7C, 0x5E, 0x86, 0x31};
99 static const u8 key_D91606F0[] = {0xED, 0x10, 0xE0, 0x36, 0xC4, 0xFE, 0x83, 0xF3, 0x75, 0x70, 0x5E, 0xF6, 0xA4, 0x40, 0x05, 0xF7};
100 static const u8 key_D91608F0[] = {0x5C, 0x77, 0x0C, 0xBB, 0xB4, 0xC2, 0x4F, 0xA2, 0x7E, 0x3B, 0x4E, 0xB4, 0xB4, 0xC8, 0x70, 0xAF};
101 static const u8 key_D91609F0[] = {0xD0, 0x36, 0x12, 0x75, 0x80, 0x56, 0x20, 0x43, 0xC4, 0x30, 0x94, 0x3E, 0x1C, 0x75, 0xD1, 0xBF};
102 static const u8 key_D9160AF0[] = {0x10, 0xA9, 0xAC, 0x16, 0xAE, 0x19, 0xC0, 0x7E, 0x3B, 0x60, 0x77, 0x86, 0x01, 0x6F, 0xF2, 0x63};
103 static const u8 key_D9160BF0[] = {0x83, 0x83, 0xF1, 0x37, 0x53, 0xD0, 0xBE, 0xFC, 0x8D, 0xA7, 0x32, 0x52, 0x46, 0x0A, 0xC2, 0xC2};
104 static const u8 key_D91611F0[] = {0x61, 0xB0, 0xC0, 0x58, 0x71, 0x57, 0xD9, 0xFA, 0x74, 0x67, 0x0E, 0x5C, 0x7E, 0x6E, 0x95, 0xB9};
105 static const u8 key_D91612F0[] = {0x9E, 0x20, 0xE1, 0xCD, 0xD7, 0x88, 0xDE, 0xC0, 0x31, 0x9B, 0x10, 0xAF, 0xC5, 0xB8, 0x73, 0x23};
106 static const u8 key_D91613F0[] = {0xEB, 0xFF, 0x40, 0xD8, 0xB4, 0x1A, 0xE1, 0x66, 0x91, 0x3B, 0x8F, 0x64, 0xB6, 0xFC, 0xB7, 0x12};
107 static const u8 key_D91614F0[] = {0xFD, 0xF7, 0xB7, 0x3C, 0x9F, 0xD1, 0x33, 0x95, 0x11, 0xB8, 0xB5, 0xBB, 0x54, 0x23, 0x73, 0x85};
108 static const u8 key_D91615F0[] = {0xC8, 0x03, 0xE3, 0x44, 0x50, 0xF1, 0xE7, 0x2A, 0x6A, 0x0D, 0xC3, 0x61, 0xB6, 0x8E, 0x5F, 0x51};
109 static const u8 key_D91616F0[] = {0x53, 0x03, 0xB8, 0x6A, 0x10, 0x19, 0x98, 0x49, 0x1C, 0xAF, 0x30, 0xE4, 0x25, 0x1B, 0x6B, 0x28};
110 static const u8 key_D91617F0[] = {0x02, 0xFA, 0x48, 0x73, 0x75, 0xAF, 0xAE, 0x0A, 0x67, 0x89, 0x2B, 0x95, 0x4B, 0x09, 0x87, 0xA3};
111 static const u8 key_D91618F0[] = {0x96, 0x96, 0x7C, 0xC3, 0xF7, 0x12, 0xDA, 0x62, 0x1B, 0xF6, 0x9A, 0x9A, 0x44, 0x44, 0xBC, 0x48};
112 static const u8 key_D91619F0[] = {0xE0, 0x32, 0xA7, 0x08, 0x6B, 0x2B, 0x29, 0x2C, 0xD1, 0x4D, 0x5B, 0xEE, 0xA8, 0xC8, 0xB4, 0xE9};
113 static const u8 key_D9161AF0[] = {0x27, 0xE5, 0xA7, 0x49, 0x52, 0xE1, 0x94, 0x67, 0x35, 0x66, 0x91, 0x0C, 0xE8, 0x9A, 0x25, 0x24};
114 static const u8 key_D91620F0[] = {0x52, 0x1C, 0xB4, 0x5F, 0x40, 0x3B, 0x9A, 0xDD, 0xAC, 0xFC, 0xEA, 0x92, 0xFD, 0xDD, 0xF5, 0x90};
115 static const u8 key_D91621F0[] = {0xD1, 0x91, 0x2E, 0xA6, 0x21, 0x14, 0x29, 0x62, 0xF6, 0xED, 0xAE, 0xCB, 0xDD, 0xA3, 0xBA, 0xFE};
116 static const u8 key_D91622F0[] = {0x59, 0x5D, 0x78, 0x4D, 0x21, 0xB2, 0x01, 0x17, 0x6C, 0x9A, 0xB5, 0x1B, 0xDA, 0xB7, 0xF9, 0xE6};
117 static const u8 key_D91623F0[] = {0xAA, 0x45, 0xEB, 0x4F, 0x62, 0xFB, 0xD1, 0x0D, 0x71, 0xD5, 0x62, 0xD2, 0xF5, 0xBF, 0xA5, 0x2F};
118 static const u8 key_D91624F0[] = {0x61, 0xB7, 0x26, 0xAF, 0x8B, 0xF1, 0x41, 0x58, 0x83, 0x6A, 0xC4, 0x92, 0x12, 0xCB, 0xB1, 0xE9};
119 static const u8 key_D91628F0[] = {0x49, 0xA4, 0xFC, 0x66, 0xDC, 0xE7, 0x62, 0x21, 0xDB, 0x18, 0xA7, 0x50, 0xD6, 0xA8, 0xC1, 0xB6};
120 static const u8 key_D91680F0[] = {0x2C, 0x22, 0x9B, 0x12, 0x36, 0x74, 0x11, 0x67, 0x49, 0xD1, 0xD1, 0x88, 0x92, 0xF6, 0xA1, 0xD8};
121 static const u8 key_D91681F0[] = {0x52, 0xB6, 0x36, 0x6C, 0x8C, 0x46, 0x7F, 0x7A, 0xCC, 0x11, 0x62, 0x99, 0xC1, 0x99, 0xBE, 0x98};
122 static const u8 key_2E5E10F0[] = {0x9D, 0x5C, 0x5B, 0xAF, 0x8C, 0xD8, 0x69, 0x7E, 0x51, 0x9F, 0x70, 0x96, 0xE6, 0xD5, 0xC4, 0xE8};
123 static const u8 key_2E5E12F0[] = {0x8A, 0x7B, 0xC9, 0xD6, 0x52, 0x58, 0x88, 0xEA, 0x51, 0x83, 0x60, 0xCA, 0x16, 0x79, 0xE2, 0x07};
124 static const u8 key_2E5E13F0[] = {0xFF, 0xA4, 0x68, 0xC3, 0x31, 0xCA, 0xB7, 0x4C, 0xF1, 0x23, 0xFF, 0x01, 0x65, 0x3D, 0x26, 0x36};
125 static const u8 key_2FD30BF0[] = {0xD8, 0x58, 0x79, 0xF9, 0xA4, 0x22, 0xAF, 0x86, 0x90, 0xAC, 0xDA, 0x45, 0xCE, 0x60, 0x40, 0x3F};
126 static const u8 keys02G_E[] = {0x9D, 0x09, 0xFD, 0x20, 0xF3, 0x8F, 0x10, 0x69, 0x0D, 0xB2, 0x6F, 0x00, 0xCC, 0xC5, 0x51, 0x2E};
127 static const u8 keys03G_E[] = {0x4F, 0x44, 0x5C, 0x62, 0xB3, 0x53, 0xC4, 0x30, 0xFC, 0x3A, 0xA4, 0x5B, 0xEC, 0xFE, 0x51, 0xEA};
128 static const u8 keys05G_E[] = {0x5D, 0xAA, 0x72, 0xF2, 0x26, 0x60, 0x4D, 0x1C, 0xE7, 0x2D, 0xC8, 0xA3, 0x2F, 0x79, 0xC5, 0x54};
129 static const u8 oneseg_310[] = {0xC7, 0x27, 0x72, 0x85, 0xAB, 0xA7, 0xF7, 0xF0, 0x4C, 0xC1, 0x86, 0xCC, 0xE3, 0x7F, 0x17, 0xCA};
130 static const u8 oneseg_300[] = {0x76, 0x40, 0x9E, 0x08, 0xDB, 0x9B, 0x3B, 0xA1, 0x47, 0x8A, 0x96, 0x8E, 0xF3, 0xF7, 0x62, 0x92};
131 static const u8 oneseg_280[] = {0x23, 0xDC, 0x3B, 0xB5, 0xA9, 0x82, 0xD6, 0xEA, 0x63, 0xA3, 0x6E, 0x2B, 0x2B, 0xE9, 0xE1, 0x54};
132 static const u8 oneseg_260_271[] = {0x22, 0x43, 0x57, 0x68, 0x2F, 0x41, 0xCE, 0x65, 0x4C, 0xA3, 0x7C, 0xC6, 0xC4, 0xAC, 0xF3, 0x60};
133 static const u8 oneseg_slim[] = {0x12, 0x57, 0x0D, 0x8A, 0x16, 0x6D, 0x87, 0x06, 0x03, 0x7D, 0xC8, 0x8B, 0x62, 0xA3, 0x32, 0xA9};
134 static const u8 ms_app_main[] = {0x1E, 0x2E, 0x38, 0x49, 0xDA, 0xD4, 0x16, 0x08, 0x27, 0x2E, 0xF3, 0xBC, 0x37, 0x75, 0x80, 0x93};
135 static const u8 demokeys_280[] = {0x12, 0x99, 0x70, 0x5E, 0x24, 0x07, 0x6C, 0xD0, 0x2D, 0x06, 0xFE, 0x7E, 0xB3, 0x0C, 0x11, 0x26};
136 static const u8 demokeys_3XX_1[] = {0x47, 0x05, 0xD5, 0xE3, 0x56, 0x1E, 0x81, 0x9B, 0x09, 0x2F, 0x06, 0xDB, 0x6B, 0x12, 0x92, 0xE0};
137 static const u8 demokeys_3XX_2[] = {0xF6, 0x62, 0x39, 0x6E, 0x26, 0x22, 0x4D, 0xCA, 0x02, 0x64, 0x16, 0x99, 0x7B, 0x9A, 0xE7, 0xB8};
138 static const u8 ebootbin_271_new[] = {0xF4, 0xAE, 0xF4, 0xE1, 0x86, 0xDD, 0xD2, 0x9C, 0x7C, 0xC5, 0x42, 0xA6, 0x95, 0xA0, 0x83, 0x88};
139 static const u8 gameshare_260_271[] = {0xF9, 0x48, 0x38, 0x0C, 0x96, 0x88, 0xA7, 0x74, 0x4F, 0x65, 0xA0, 0x54, 0xC2, 0x76, 0xD9, 0xB8};
140 static const u8 gameshare_280[] = {0x2D, 0x86, 0x77, 0x3A, 0x56, 0xA4, 0x4F, 0xDD, 0x3C, 0x16, 0x71, 0x93, 0xAA, 0x8E, 0x11, 0x43};
141 static const u8 gameshare_300[] = {0x78, 0x1A, 0xD2, 0x87, 0x24, 0xBD, 0xA2, 0x96, 0x18, 0x3F, 0x89, 0x36, 0x72, 0x90, 0x92, 0x85};
142 static const u8 gameshare_310[] = {0xC9, 0x7D, 0x3E, 0x0A, 0x54, 0x81, 0x6E, 0xC7, 0x13, 0x74, 0x99, 0x74, 0x62, 0x18, 0xE7, 0xDD};
143 static const u8 key_380210F0[] = {0x32, 0x2C, 0xFA, 0x75, 0xE4, 0x7E, 0x93, 0xEB, 0x9F, 0x22, 0x80, 0x85, 0x57, 0x08, 0x98, 0x48};
144 static const u8 key_380280F0[] = {0x97, 0x09, 0x12, 0xD3, 0xDB, 0x02, 0xBD, 0xD8, 0xE7, 0x74, 0x51, 0xFE, 0xF0, 0xEA, 0x6C, 0x5C};
145 static const u8 key_380283F0[] = {0x34, 0x20, 0x0C, 0x8E, 0xA1, 0x86, 0x79, 0x84, 0xAF, 0x13, 0xAE, 0x34, 0x77, 0x6F, 0xEA, 0x89};
146 static const u8 key_407810F0[] = {0xAF, 0xAD, 0xCA, 0xF1, 0x95, 0x59, 0x91, 0xEC, 0x1B, 0x27, 0xD0, 0x4E, 0x8A, 0xF3, 0x3D, 0xE7};
147 static const u8 drmkeys_6XX_1[] = {0x36, 0xEF, 0x82, 0x4E, 0x74, 0xFB, 0x17, 0x5B, 0x14, 0x14, 0x05, 0xF3, 0xB3, 0x8A, 0x76, 0x18};
148 static const u8 drmkeys_6XX_2[] = {0x21, 0x52, 0x5D, 0x76, 0xF6, 0x81, 0x0F, 0x15, 0x2F, 0x4A, 0x40, 0x89, 0x63, 0xA0, 0x10, 0x55};
149 static const u8 pauth_98b83b5d_1[] = {0xB0, 0x24, 0xC8, 0x16, 0x43, 0xE8, 0xF0, 0x1C, 0x8C, 0x30, 0x67, 0x73, 0x3E, 0x96, 0x35, 0xEF};
150 static const u8 pauth_98b83b5d_xor[] = {0xA9, 0x1E, 0xDD, 0x7B, 0x09, 0xBB, 0x22, 0xB5, 0x9D, 0xA3, 0x30, 0x69, 0x13, 0x6E, 0x0E, 0xD8};
151 static const u8 pauth_f7aa47f6_1[] = {0xC5, 0xFB, 0x69, 0x03, 0x20, 0x7A, 0xCF, 0xBA, 0x2C, 0x90, 0xF8, 0xB8, 0x4D, 0xD2, 0xF1, 0xDE};
152 static const u8 pauth_f7aa47f6_2[] = {0x3A, 0x6B, 0x48, 0x96, 0x86, 0xA5, 0xC8, 0x80, 0x69, 0x6C, 0xE6, 0x4B, 0xF6, 0x04, 0x17, 0x44};
153 static const u8 pauth_f7aa47f6_xor[] = {0xA9, 0x1E, 0xDD, 0x7B, 0x09, 0xBB, 0x22, 0xB5, 0x9D, 0xA3, 0x30, 0x69, 0x13, 0x6E, 0x0E, 0xD8};
154
155 // PRXDecrypter 144-byte tag keys.
156 static const u32 g_key0[] = {
157 0x7b21f3be, 0x299c5e1d, 0x1c9c5e71, 0x96cb4645, 0x3c9b1be0, 0xeb85de3d,
158 0x4a7f2022, 0xc2206eaa, 0xd50b3265, 0x55770567, 0x3c080840, 0x981d55f2,
159 0x5fd8f6f3, 0xee8eb0c5, 0x944d8152, 0xf8278651, 0x2705bafa, 0x8420e533,
160 0x27154ae9, 0x4819aa32, 0x59a3aa40, 0x2cb3cf65, 0xf274466d, 0x3a655605,
161 0x21b0f88f, 0xc5b18d26, 0x64c19051, 0xd669c94e, 0xe87035f2, 0x9d3a5909,
162 0x6f4e7102, 0xdca946ce, 0x8416881b, 0xbab097a5, 0x249125c6, 0xb34c0872};
163 static const u32 g_key2[] = {
164 0xccfda932, 0x51c06f76, 0x046dcccf, 0x49e1821e, 0x7d3b024c, 0x9dda5865,
165 0xcc8c9825, 0xd1e97db5, 0x6874d8cb, 0x3471c987, 0x72edb3fc, 0x81c8365d,
166 0xe161e33a, 0xfc92db59, 0x2009b1ec, 0xb1a94ce4, 0x2f03696b, 0x87e236d8,
167 0x3b2b8ce9, 0x0305e784, 0xf9710883, 0xb039db39, 0x893bea37, 0xe74d6805,
168 0x2a5c38bd, 0xb08dc813, 0x15b32375, 0x46be4525, 0x0103fd90, 0xa90e87a2,
169 0x52aba66a, 0x85bf7b80, 0x45e8ce63, 0x4dd716d3, 0xf5e30d2d, 0xaf3ae456};
170 static const u32 g_key3[] = {
171 0xa6c8f5ca, 0x6d67c080, 0x924f4d3a, 0x047ca06a, 0x08640297, 0x4fd4a758,
172 0xbd685a87, 0x9b2701c2, 0x83b62a35, 0x726b533c, 0xe522fa0c, 0xc24b06b4,
173 0x459d1cac, 0xa8c5417b, 0x4fea62a2, 0x0615d742, 0x30628d09, 0xc44fab14,
174 0x69ff715e, 0xd2d8837d, 0xbeed0b8b, 0x1e6e57ae, 0x61e8c402, 0xbe367a06,
175 0x543f2b5e, 0xdb3ec058, 0xbe852075, 0x1e7e4dcc, 0x1564ea55, 0xec7825b4,
176 0xc0538cad, 0x70f72c7f, 0x49e8c3d0, 0xeda97ec5, 0xf492b0a4, 0xe05eb02a};
177 static const u32 g_key44[] = {
178 0xef80e005, 0x3a54689f, 0x43c99ccd, 0x1b7727be, 0x5cb80038, 0xdd2efe62,
179 0xf369f92c, 0x160f94c5, 0x29560019, 0xbf3c10c5, 0xf2ce5566, 0xcea2c626,
180 0xb601816f, 0x64e7481e, 0x0c34debd, 0x98f29cb0, 0x3fc504d7, 0xc8fb39f0,
181 0x0221b3d8, 0x63f936a2, 0x9a3a4800, 0x6ecc32e3, 0x8e120cfd, 0xb0361623,
182 0xaee1e689, 0x745502eb, 0xe4a6c61c, 0x74f23eb4, 0xd7fa5813, 0xb01916eb,
183 0x12328457, 0xd2bc97d2, 0x646425d8, 0x328380a5, 0x43da8ab1, 0x4b122ac9};
184 static const u32 g_key20[] = {
185 0x33b50800, 0xf32f5fcd, 0x3c14881f, 0x6e8a2a95, 0x29feefd5, 0x1394eae3,
186 0xbd6bd443, 0x0821c083, 0xfab379d3, 0xe613e165, 0xf5a754d3, 0x108b2952,
187 0x0a4b1e15, 0x61eadeba, 0x557565df, 0x3b465301, 0xae54ecc3, 0x61423309,
188 0x70c9ff19, 0x5b0ae5ec, 0x989df126, 0x9d987a5f, 0x55bc750e, 0xc66eba27,
189 0x2de988e8, 0xf76600da, 0x0382dccb, 0x5569f5f2, 0x8e431262, 0x288fe3d3,
190 0x656f2187, 0x37d12e9c, 0x2f539eb4, 0xa492998e, 0xed3958f7, 0x39e96523};
191 static const u32 g_key3A[] = {
192 0x67877069, 0x3abd5617, 0xc23ab1dc, 0xab57507d, 0x066a7f40, 0x24def9b9,
193 0x06f759e4, 0xdcf524b1, 0x13793e5e, 0x0359022d, 0xaae7e1a2, 0x76b9b2fa,
194 0x9a160340, 0x87822fba, 0x19e28fbb, 0x9e338a02, 0xd8007e9a, 0xea317af1,
195 0x630671de, 0x0b67ca7c, 0x865192af, 0xea3c3526, 0x2b448c8e, 0x8b599254,
196 0x4602e9cb, 0x4de16cda, 0xe164d5bb, 0x07ecd88e, 0x99ffe5f8, 0x768800c1,
197 0x53b091ed, 0x84047434, 0xb426dbbc, 0x36f948bb, 0x46142158, 0x749bb492};
198 static const u32 g_keyEBOOT1xx[] = {
199 0x18CB69EF, 0x158E8912, 0xDEF90EBB, 0x4CB0FB23, 0x3687EE18, 0x868D4A6E,
200 0x19B5C756, 0xEE16551D, 0xE7CB2D6C, 0x9747C660, 0xCE95143F, 0x2956F477,
201 0x03824ADE, 0x210C9DF1, 0x5029EB24, 0x81DFE69F, 0x39C89B00, 0xB00C8B91,
202 0xEF2DF9C2, 0xE13A93FC, 0x8B94A4A8, 0x491DD09D, 0x686A400D, 0xCED4C7E4,
203 0x96C8B7C9, 0x1EAADC28, 0xA4170B84, 0x505D5DDC, 0x5DA6C3CF, 0x0E5DFA2D,
204 0x6E7919B5, 0xCE5E29C7, 0xAAACDB94, 0x45F70CDD, 0x62A73725, 0xCCE6563D};
205 static const u32 g_keyEBOOT2xx[] = {
206 0xDA8E36FA, 0x5DD97447, 0x76C19874, 0x97E57EAF, 0x1CAB09BD, 0x9835BAC6,
207 0x03D39281, 0x03B205CF, 0x2882E734, 0xE714F663, 0xB96E2775, 0xBD8AAFC7,
208 0x1DD3EC29, 0xECA4A16C, 0x5F69EC87, 0x85981E92, 0x7CFCAE21, 0xBAE9DD16,
209 0xE6A97804, 0x2EEE02FC, 0x61DF8A3D, 0xDD310564, 0x9697E149, 0xC2453F3B,
210 0xF91D8456, 0x39DA6BC8, 0xB3E5FEF5, 0x89C593A3, 0xFB5C8ABC, 0x6C0B7212,
211 0xE10DD3CB, 0x98D0B2A8, 0x5FD61847, 0xF0DC2357, 0x7701166A, 0x0F5C3B68};
212 static const u32 g_demokeys_280[] = {
213 0x2A5282B4, 0x8706DDA5, 0x4C88EC1C, 0xD504708E, 0x72634DD2, 0xDD2E2F60,
214 0xE3D5FDB5, 0xE050637D, 0x295C69AC, 0x7B61F57D, 0x594412B0, 0x13D925CE,
215 0x2A6BE8DD, 0xBC9594E6, 0x1F4A8A39, 0xC56B5909, 0x52CFB2F7, 0x03EE089F,
216 0x5CA57A21, 0xDB64090F, 0x5E9A56F3, 0x13C56633, 0xD9C48D1D, 0xCDA05972,
217 0xD09E13B2, 0x7DEDD3DF, 0x364387BB, 0xCB207488, 0xBEC14B3F, 0x7C9C0D11,
218 0x9916ED40, 0x65909519, 0xC55BB1B3, 0xE997E084, 0xB483438B, 0xB8A2D255};
219 static const u32 g_keyUPDATER[] = {
220 0xA5603CBF, 0xD7482441, 0xF65764CC, 0x1F90060B, 0x4EA73E45, 0xE551D192,
221 0xE7B75D8A, 0x465A506E, 0x40FB1022, 0x2C273350, 0x8096DA44, 0x9947198E,
222 0x278DEE77, 0x745D062E, 0xC148FA45, 0x832582AF, 0x5FDB86DA, 0xCB15C4CE,
223 0x2524C62F, 0x6C2EC3B1, 0x369BE39E, 0xF7EB1FC4, 0x1E51CE1A, 0xD70536F4,
224 0xC34D39D8, 0x7418FB13, 0xE3C84DE1, 0xB118F03C, 0xA2018D4E, 0xE6D8770D,
225 0x5720F390, 0x17F96341, 0x60A4A68F, 0x1327DD28, 0x05944C64, 0x0C2C4C12};
226 static const u32 g_keyMEIMG250[] = {
227 0xA381FEBC, 0x99B9D5C9, 0x6C560A8D, 0x30309F95, 0x792646CC, 0x82B64E5E,
228 0x1A3951AD, 0x0A182EC4, 0xC46131B4, 0x77C50C8A, 0x325F16C6, 0x02D1942E,
229 0x0AA38AC4, 0x2A940AC6, 0x67034726, 0xE52DB133, 0xD2EF2107, 0x85C81E90,
230 0xC8D164BA, 0xC38DCE1D, 0x948BA275, 0x0DB84603, 0xE2473637, 0xCD74FCDA,
231 0x588E3D66, 0x6D28E822, 0x891E548B, 0xF53CF56D, 0x0BBDDB66, 0xC4B286AA,
232 0x2BEBBC4B, 0xFC261FF4, 0x92B8E705, 0xDCEE6952, 0x5E0442E5, 0x8BEB7F21};
233 static const u32 g_keyMEIMG260[] = {
234 0x11BFD698, 0xD7F9B324, 0xDD524927, 0x16215B86, 0x504AC36D, 0x5843B217,
235 0xE5A0DA47, 0xBB73A1E7, 0x2915DB35, 0x375CFD3A, 0xBB70A905, 0x272BEFCA,
236 0x2E960791, 0xEA0799BB, 0xB85AE6C8, 0xC9CAF773, 0x250EE641, 0x06E74A9E,
237 0x5244895D, 0x466755A5, 0x9A84AF53, 0xE1024174, 0xEEBA031E, 0xED80B9CE,
238 0xBC315F72, 0x5821067F, 0xE8313058, 0xD2D0E706, 0xE6D8933E, 0xD7D17FB4,
239 0x505096C4, 0xFDA50B3B, 0x4635AE3D, 0xEB489C8A, 0x422D762D, 0x5A8B3231};
240 static const u32 g_keyDEMOS27X[] = {
241 0x1ABF102F, 0xD596D071, 0x6FC552B2, 0xD4F2531F, 0xF025CDD9, 0xAF9AAF03,
242 0xE0CF57CF, 0x255494C4, 0x7003675E, 0x907BC884, 0x002D4EE4, 0x0B687A0D,
243 0x9E3AA44F, 0xF58FDA81, 0xEC26AC8C, 0x3AC9B49D, 0x3471C037, 0xB0F3834D,
244 0x10DC4411, 0xA232EA31, 0xE2E5FA6B, 0x45594B03, 0xE43A1C87, 0x31DAD9D1,
245 0x08CD7003, 0xFA9C2FDF, 0x5A891D25, 0x9B5C1934, 0x22F366E5, 0x5F084A32,
246 0x695516D5, 0x2245BE9F, 0x4F6DD705, 0xC4B8B8A1, 0xBC13A600, 0x77B7FC3B};
247 static const u32 g_keyUNK1[] = {
248 0x33B50800, 0xF32F5FCD, 0x3C14881F, 0x6E8A2A95, 0x29FEEFD5, 0x1394EAE3,
249 0xBD6BD443, 0x0821C083, 0xFAB379D3, 0xE613E165, 0xF5A754D3, 0x108B2952,
250 0x0A4B1E15, 0x61EADEBA, 0x557565DF, 0x3B465301, 0xAE54ECC3, 0x61423309,
251 0x70C9FF19, 0x5B0AE5EC, 0x989DF126, 0x9D987A5F, 0x55BC750E, 0xC66EBA27,
252 0x2DE988E8, 0xF76600DA, 0x0382DCCB, 0x5569F5F2, 0x8E431262, 0x288FE3D3,
253 0x656F2187, 0x37D12E9C, 0x2F539EB4, 0xA492998E, 0xED3958F7, 0x39E96523};
254 static const u32 g_key_GAMESHARE1xx[] = {
255 0x721B53E8, 0xFC3E31C6, 0xF85BA2A2, 0x3CF0AC72, 0x54EEA7AB, 0x5959BFCB,
256 0x54B8836B, 0xBC431313, 0x989EF2CF, 0xF0CE36B2, 0x98BA4CF8, 0xE971C931,
257 0xA0375DC8, 0x08E52FA0, 0xAC0DD426, 0x57E4D601, 0xC56E61C7, 0xEF1AB98A,
258 0xD1D9F8F4, 0x5FE9A708, 0x3EF09D07, 0xFA0C1A8C, 0xA91EEA5C, 0x58F482C5,
259 0x2C800302, 0x7EE6F6C3, 0xFF6ABBBB, 0x2110D0D0, 0xD3297A88, 0x980012D3,
260 0xDC59C87B, 0x7FDC5792, 0xDB3F5DA6, 0xFC23B787, 0x22698ED3, 0xB680E812};
261 static const u32 g_key_GAMESHARE2xx[] = {
262 0x94A757C7, 0x9FD39833, 0xF8508371, 0x328B0B29, 0x2CBCB9DA, 0x2918B9C6,
263 0x944C50BA, 0xF1DCE7D0, 0x640C3966, 0xC90B3D08, 0xF4AD17BA, 0x6CA0F84B,
264 0xF7767C67, 0xA4D3A55A, 0x4A085C6A, 0x6BB27071, 0xFA8B38FB, 0x3FDB31B8,
265 0x8B7196F2, 0xDB9BED4A, 0x51625B84, 0x4C1481B4, 0xF684F508, 0x30B44770,
266 0x93AA8E74, 0x90C579BC, 0x246EC88D, 0x2E051202, 0xC774842E, 0xA185D997,
267 0x7A2B3ADD, 0xFE835B6D, 0x508F184D, 0xEB4C4F13, 0x0E1993D3, 0xBA96DFD2};
268 static const u32 g_key_INDEXDAT1xx[] = {
269 0x76CB00AF, 0x111CE62F, 0xB7B27E36, 0x6D8DE8F9, 0xD54BF16A, 0xD9E90373,
270 0x7599D982, 0x51F82B0E, 0x636103AD, 0x8E40BC35, 0x2F332C94, 0xF513AAE9,
271 0xD22AFEE9, 0x04343987, 0xFC5BB80C, 0x12349D89, 0x14A481BB, 0x25ED3AE8,
272 0x7D500E4F, 0x43D1B757, 0x7B59FDAD, 0x4CFBBF34, 0xC3D17436, 0xC1DA21DB,
273 0xA34D8C80, 0x962B235D, 0x3E420548, 0x09CF9FFE, 0xD4883F5C, 0xD90E9CB5,
274 0x00AEF4E9, 0xF0886DE9, 0x62A58A5B, 0x52A55546, 0x971941B5, 0xF5B79FAC};
275
276 struct TAG_INFO
277 {
278 u32 tag; // 4 byte value at offset 0xD0 in the PRX file
279 const u32 *key; // "step1_result" use for XOR step
280 u8 code;
281 u8 codeExtra;
282 };
283
284 static const TAG_INFO g_tagInfo[] =
285 {
286 { 0x00000000, g_key0, 0x42 },
287 { 0x02000000, g_key2, 0x45 },
288 { 0x03000000, g_key3, 0x46 },
289 { 0x4467415d, g_key44, 0x59, 0x59 },
290 { 0x207bbf2f, g_key20, 0x5A, 0x5A },
291 { 0x3ace4dce, g_key3A, 0x5B, 0x5B },
292 { 0x07000000, g_key_INDEXDAT1xx, 0x4A },
293 { 0x08000000, g_keyEBOOT1xx, 0x4B },
294 { 0xC0CB167C, g_keyEBOOT2xx, 0x5D, 0x5D },
295 { 0x7F24BDCD, g_demokeys_280, 0x60, 0x60 },
296 { 0x0B000000, g_keyUPDATER, 0x4E },
297 { 0x0C000000, g_keyDEMOS27X, 0x4F },
298 { 0x0F000000, g_keyMEIMG250, 0x52 },
299 { 0x862648D1, g_keyMEIMG260, 0x52, 0x52 },
300 { 0x207BBF2F, g_keyUNK1, 0x5A, 0x5A },
301 { 0x09000000, g_key_GAMESHARE1xx, 0x4C },
302 { 0xBB67C59F, g_key_GAMESHARE2xx, 0x5E, 0x5E }
303 };
304
GetTagInfo(u32 tagFind)305 static const TAG_INFO *GetTagInfo(u32 tagFind)
306 {
307 for (u32 iTag = 0; iTag < sizeof(g_tagInfo)/sizeof(TAG_INFO); iTag++)
308 if (g_tagInfo[iTag].tag == tagFind)
309 return &g_tagInfo[iTag];
310 return NULL; // not found
311 }
312
313 ////////// Decryption 2 //////////
314
315 struct TAG_INFO2
316 {
317 u32 tag; // 4 byte value at offset 0xD0 in the PRX file
318 const u8 *key; // 16 bytes keys
319 u8 code; // code for scramble
320 u8 type;
321 const u8 *seed;
322 };
323
324 static const TAG_INFO2 g_tagInfo2[] =
325 {
326 { 0x4C9494F0, keys660_k1, 0x43 },
327 { 0x4C9495F0, keys660_k2, 0x43 },
328 { 0x4C9490F0, keys660_k3, 0x43 },
329 { 0x4C9491F0, keys660_k8, 0x43 },
330 { 0x4C9493F0, keys660_k4, 0x43 },
331 { 0x4C9497F0, keys660_k5, 0x43 },
332 { 0x4C9492F0, keys660_k6, 0x43 },
333 { 0x4C9496F0, keys660_k7, 0x43 },
334 { 0x457B90F0, keys660_v1, 0x5B },
335 { 0x457B91F0, keys660_v7, 0x5B },
336 { 0x457B92F0, keys660_v6, 0x5B },
337 { 0x457B93F0, keys660_v3, 0x5B },
338 { 0x380290F0, keys660_v2, 0x5A },
339 { 0x380291F0, keys660_v8, 0x5A },
340 { 0x380292F0, keys660_v4, 0x5A },
341 { 0x380293F0, keys660_v5, 0x5A },
342 { 0x4C948CF0, keys639_k3, 0x43 },
343 { 0x4C948DF0, keys638_k4, 0x43 },
344 { 0x4C948BF0, keys636_k2, 0x43 },
345 { 0x4C948AF0, keys636_k1, 0x43 },
346 { 0x4C9487F0, keys630_k8, 0x43 },
347 { 0x457B83F0, keys630_k7, 0x5B },
348 { 0x4C9486F0, keys630_k6, 0x43 },
349 { 0x457B82F0, keys630_k5, 0x5B },
350 { 0x457B81F0, keys630_k4, 0x5B },
351 { 0x4C9485F0, keys630_k3, 0x43 },
352 { 0x457B80F0, keys630_k2, 0x5B },
353 { 0x4C9484F0, keys630_k1, 0x43 },
354 { 0x457B28F0, keys620_e, 0x5B },
355 { 0x457B0CF0, keys620_a, 0x5B },
356 { 0x380228F0, keys620_5v, 0x5A },
357 { 0x4C942AF0, keys620_5k, 0x43 },
358 { 0x4C9428F0, keys620_5, 0x43 },
359 { 0x4C941DF0, keys620_1, 0x43 },
360 { 0x4C941CF0, keys620_0, 0x43 },
361 { 0x4C9422F0, keys600_2, 0x43 },
362 { 0x4C941EF0, keys600_1, 0x43 },
363 { 0x4C9429F0, keys570_5k, 0x43 },
364 { 0x457B0BF0, keys505_a, 0x5B },
365 { 0x4C9419F0, keys505_1, 0x43 },
366 { 0x4C9418F0, keys505_0, 0x43 },
367 { 0x457B1EF0, keys500_c, 0x5B },
368 { 0x4C941FF0, keys500_2, 0x43 },
369 { 0x4C9417F0, keys500_1, 0x43 },
370 { 0x4C9416F0, keys500_0, 0x43 },
371 { 0x4C9414F0, keys390_0, 0x43 },
372 { 0x4C9415F0, keys390_1, 0x43 },
373 { 0x4C9412F0, keys370_0, 0x43 },
374 { 0x4C9413F0, keys370_1, 0x43 },
375 { 0x457B10F0, keys370_2, 0x5B },
376 { 0x4C940DF0, keys360_0, 0x43 },
377 { 0x4C9410F0, keys360_1, 0x43 },
378 { 0x4C940BF0, keys330_0, 0x43 },
379 { 0x457B0AF0, keys330_1, 0x5B },
380 { 0x38020AF0, keys330_2, 0x5A },
381 { 0x4C940AF0, keys330_3, 0x43 },
382 { 0x4C940CF0, keys330_4, 0x43 },
383 { 0xcfef09f0, keys310_0, 0x62 },
384 { 0x457b08f0, keys310_1, 0x5B },
385 { 0x380208F0, keys310_2, 0x5A },
386 { 0xcfef08f0, keys310_3, 0x62 },
387 { 0xCFEF07F0, keys303_0, 0x62 },
388 { 0xCFEF06F0, keys300_0, 0x62 },
389 { 0x457B06F0, keys300_1, 0x5B },
390 { 0x380206F0, keys300_2, 0x5A },
391 { 0xCFEF05F0, keys280_0, 0x62 },
392 { 0x457B05F0, keys280_1, 0x5B },
393 { 0x380205F0, keys280_2, 0x5A },
394 { 0x16D59E03, keys260_0, 0x62 },
395 { 0x76202403, keys260_1, 0x5B },
396 { 0x0F037303, keys260_2, 0x5A },
397 { 0x4C940FF0, key_2DA8, 0x43 },
398 { 0x4467415D, key_22E0, 0x59 },
399 { 0x00000000, key_21C0, 0x42 },
400 { 0x01000000, key_2250, 0x43 },
401 { 0x2E5E10F0, key_2E5E10F0, 0x48 },
402 { 0x2E5E12F0, key_2E5E12F0, 0x48 },
403 { 0x2E5E13F0, key_2E5E13F0, 0x48 },
404 { 0x2FD30BF0, key_2FD30BF0, 0x47 },
405 { 0xD91605F0, key_D91605F0, 0x5D, 2},
406 { 0xD91606F0, key_D91606F0, 0x5D, 2},
407 { 0xD91608F0, key_D91608F0, 0x5D, 2},
408 { 0xD91609F0, key_D91609F0, 0x5D, 2},
409 { 0xD9160AF0, key_D9160AF0, 0x5D, 2},
410 { 0xD9160BF0, key_D9160BF0, 0x5D, 2},
411 { 0xD91611F0, key_D91611F0, 0x5D, 2},
412 { 0xD91612F0, key_D91612F0, 0x5D, 2},
413 { 0xD91613F0, key_D91613F0, 0x5D, 2},
414 { 0xD91614F0, key_D91614F0, 0x5D, 2},
415 { 0xD91615F0, key_D91615F0, 0x5D, 2},
416 { 0xD91616F0, key_D91616F0, 0x5D, 2},
417 { 0xD91617F0, key_D91617F0, 0x5D, 2},
418 { 0xD91618F0, key_D91618F0, 0x5D, 2},
419 { 0xD91619F0, key_D91619F0, 0x5D, 2},
420 { 0xD9161AF0, key_D9161AF0, 0x5D, 2},
421 { 0xD91620F0, key_D91620F0, 0x5D, 2},
422 { 0xD91621F0, key_D91621F0, 0x5D, 2},
423 { 0xD91622F0, key_D91622F0, 0x5D, 2},
424 { 0xD91623F0, key_D91623F0, 0x5D, 2},
425 { 0xD91624F0, key_D91624F0, 0x5D, 2},
426 { 0xD91628F0, key_D91628F0, 0x5D, 2},
427 { 0xD91680F0, key_D91680F0, 0x5D, 6},
428 { 0xD91681F0, key_D91681F0, 0x5D, 6},
429 { 0xD82310F0, keys02G_E, 0x51 },
430 { 0xD8231EF0, keys03G_E, 0x51 },
431 { 0xD82328F0, keys05G_E, 0x51 },
432 { 0x279D08F0, oneseg_310, 0x61 },
433 { 0x279D06F0, oneseg_300, 0x61 },
434 { 0x279D05F0, oneseg_280, 0x61 },
435 { 0xD66DF703, oneseg_260_271, 0x61 },
436 { 0x279D10F0, oneseg_slim, 0x61 },
437 { 0x3C2A08F0, ms_app_main, 0x67 },
438 { 0xADF305F0, demokeys_280, 0x60 },
439 { 0xADF306F0, demokeys_3XX_1, 0x60 },
440 { 0xADF308F0, demokeys_3XX_2, 0x60 },
441 { 0x8004FD03, ebootbin_271_new, 0x5D, 2 },
442 { 0x0A35EA03, gameshare_260_271, 0x5E },
443 { 0x7B0505F0, gameshare_280, 0x5E },
444 { 0x7B0506F0, gameshare_300, 0x5E },
445 { 0x7B0508F0, gameshare_310, 0x5E },
446 { 0x380210F0, key_380210F0, 0x5A },
447 { 0x380280F0, key_380280F0, 0x5A },
448 { 0x380283F0, key_380283F0, 0x5A },
449 { 0x407810F0, key_407810F0, 0x6A },
450 { 0xE92410F0, drmkeys_6XX_1, 0x40 },
451 { 0x692810F0, drmkeys_6XX_2, 0x40 },
452 { 0x2FD313F0, pauth_98b83b5d_1, 0x47, 5, pauth_98b83b5d_xor },
453 { 0x2FD312F0, pauth_f7aa47f6_1, 0x47, 5, pauth_f7aa47f6_xor },
454 { 0x2FD311F0, pauth_f7aa47f6_2, 0x47, 5, pauth_f7aa47f6_xor },
455 };
456
GetTagInfo2(u32 tagFind)457 static const TAG_INFO2 *GetTagInfo2(u32 tagFind)
458 {
459 for (u32 iTag = 0; iTag < sizeof(g_tagInfo2) / sizeof(TAG_INFO2); iTag++)
460 {
461 if (g_tagInfo2[iTag].tag == tagFind)
462 {
463 return &g_tagInfo2[iTag];
464 }
465 }
466
467 return NULL; // not found
468 }
469
expandSeed(const u8 * seed,int key,const u8 * bonusSeed=nullptr)470 static std::array<u8, 0x90> expandSeed(const u8 *seed, int key, const u8 *bonusSeed = nullptr)
471 {
472 std::array<u8, 0x90> expandedSeed;
473
474 // perform some AES-CTR like encryption of seed
475 for (auto i = 0u; i < expandedSeed.size(); i += 0x10)
476 {
477 memcpy(expandedSeed.data()+i, seed, 0x10);
478 expandedSeed[i] = i/0x10;
479 }
480
481 kirk7(expandedSeed.data(), expandedSeed.data(), expandedSeed.size(), key);
482
483 if (bonusSeed)
484 {
485 for (auto i = 0u; i < expandedSeed.size(); ++i)
486 {
487 expandedSeed[i] ^= bonusSeed[i % 0x10];
488 }
489 }
490
491 return expandedSeed;
492 }
493
494 template<typename It>
decryptKirkHeader(u8 * outbuf,const u8 * inbuf,It xorbuf,int key)495 static void decryptKirkHeader(u8 *outbuf, const u8 *inbuf, It xorbuf, int key)
496 {
497 for (auto i = 0; i < 0x40; ++i)
498 {
499 outbuf[i] = inbuf[i] ^ *xorbuf++;
500 }
501
502 kirk7(outbuf, outbuf, 0x40, key);
503
504 for (auto i = 0; i < 0x40; ++i)
505 {
506 outbuf[i] = outbuf[i] ^ *xorbuf++;
507 }
508 }
509
510 template <typename T>
decryptKirkHeaderType0(u8 * outbuf,const u8 * inbuf,T xorbuf,int key)511 static void decryptKirkHeaderType0(u8 *outbuf, const u8 *inbuf, T xorbuf, int key)
512 {
513 for (auto i = 0; i < 0x70; ++i)
514 {
515 outbuf[i] = inbuf[i] ^ xorbuf[i+0x14];
516 }
517
518 kirk7(outbuf, outbuf, 0x70, key);
519
520 for (auto i = 0; i < 0x70; ++i)
521 {
522 outbuf[i] = outbuf[i] ^ xorbuf[i+0x20];
523 }
524 }
525
526 struct PRXType0
527 {
PRXType0PRXType0528 explicit PRXType0(const u8 *prx)
529 {
530 memcpy(tag, prx+0xD0, sizeof(tag));
531 memcpy(sha1, prx+0xD4, sizeof(sha1));
532 memcpy(unused, prx+0xE8, sizeof(unused));
533 memcpy(kirkBlock, prx+0x110, 0x40); // key data
534 memcpy(kirkBlock+0x40, prx+0x80, sizeof(kirkBlock)-0x40);
535 memcpy(prxHeader, prx, sizeof(prxHeader));
536 }
537
538 u8 tag[4];
539 u8 sha1[0x14];
540 u8 unused[0x28];
541 u8 kirkBlock[0x90];
542 u8 prxHeader[0x80];
543 };
544
545 static_assert(sizeof(PRXType0) == 0x150, "inconsistent size of PRX Type 0");
546
547 struct PRXType1
548 {
PRXType1PRXType1549 explicit PRXType1(const u8 *prx)
550 {
551 memcpy(tag, prx+0xD0, sizeof(tag));
552 memcpy(sha1, prx+0xD4, sizeof(sha1));
553 memcpy(unused, prx+0xE8, sizeof(unused));
554 memcpy(kirkBlock, prx+0x110, 0x40); // key data
555 memcpy(kirkBlock+0x40, prx+0x80, sizeof(kirkBlock)-0x40);
556 memcpy(prxHeader, prx, sizeof(prxHeader));
557 }
558
decryptPRXType1559 void decrypt(int key)
560 {
561 kirk7(sha1+0xC, sha1+0xC, 0xA0, key);
562 }
563
564 u8 tag[4];
565 u8 sha1[0x14];
566 u8 unused[0x28];
567 u8 kirkBlock[0x90];
568 u8 prxHeader[0x80];
569 };
570
571 static_assert(sizeof(PRXType1) == 0x150, "inconsistent size of PRX Type 1");
572
573 struct PRXType2
574 {
PRXType2PRXType2575 explicit PRXType2(const u8 *prx)
576 {
577 memcpy(tag, prx+0xD0, sizeof(tag));
578 memset(empty, 0, sizeof(empty));
579 memcpy(id, prx+0x140, sizeof(id));
580 memcpy(sha1, prx+0x12C, sizeof(sha1));
581 // kirk header is split between 0x80->0xB0 and 0xC0->0xD0
582 memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
583 memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
584 memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
585 memcpy(prxHeader, prx, sizeof(prxHeader));
586 }
587
decryptPRXType2588 void decrypt(int key)
589 {
590 kirk7(id, id, 0x60, key);
591 }
592
593 u8 tag[4];
594 u8 empty[0x58];
595 u8 id[0x10];
596 u8 sha1[0x14];
597 u8 kirkHeader[0x40];
598 u8 kirkMetadata[0x10];
599 u8 prxHeader[0x80];
600 };
601 static_assert(sizeof(PRXType2) == 0x150, "inconsistent size of PRX Type 2");
602
603 struct PRXType5
604 {
PRXType5PRXType5605 explicit PRXType5(const u8 *prx)
606 {
607 memcpy(tag, prx+0xD0, sizeof(tag));
608 memset(empty, 0, sizeof(empty));
609 memcpy(id, prx+0x140, sizeof(id));
610 memcpy(sha1, prx+0x12C, sizeof(sha1));
611 // kirk header is split between 0x80->0xB0 and 0xC0->0xD0
612 memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
613 memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
614 memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
615 memcpy(prxHeader, prx, sizeof(prxHeader));
616 }
617
decryptPRXType5618 void decrypt(int key, const u8 *xor1, const u8 *xor2)
619 {
620 // first step is to decrypt kirk header + SHA1
621 u8 data[0x50];
622 memcpy(data, kirkHeader, sizeof(kirkHeader));
623 memcpy(data+sizeof(kirkHeader), sha1, 0x10);
624
625 for (auto i = 0; i < 0x50; ++i)
626 {
627 if (xor1)
628 {
629 data[i] ^= xor1[i % 0x10];
630 }
631
632 if (xor2)
633 {
634 data[i] ^= xor2[i % 0x10];
635 }
636 }
637
638 kirk7(data, data, 0x50, key);
639
640 // copy the result back
641 memcpy(kirkHeader, data, sizeof(kirkHeader));
642 memcpy(sha1, data+sizeof(kirkHeader), 0x10);
643
644 // second step is a XOR then decrypt id through to kirk header
645 if (xor1)
646 {
647 u8 *p = id;
648 for (auto i = 0; i < 0x60; ++i)
649 {
650 p[i] ^= xor1[i % 0x10];
651 }
652 }
653
654 kirk7(id, id, 0x60, key);
655 }
656
657 u8 tag[4];
658 u8 empty[0x58];
659 u8 id[0x10];
660 u8 sha1[0x14];
661 u8 kirkHeader[0x40];
662 u8 kirkMetadata[0x10];
663 u8 prxHeader[0x80];
664 };
665 static_assert(sizeof(PRXType5) == 0x150, "inconsistent size of PRX Type 5");
666
667 struct PRXType6
668 {
PRXType6PRXType6669 explicit PRXType6(const u8 *prx)
670 {
671 memcpy(tag, prx+0xD0, sizeof(tag));
672 memset(empty, 0, sizeof(empty));
673 memcpy(ecdsaSignatureTail, prx+0x10C, sizeof(ecdsaSignatureTail));
674 memcpy(id, prx+0x140, sizeof(id));
675 memcpy(sha1, prx+0x12C, sizeof(sha1));
676 // kirk header is split between 0x80->0xB0 and 0xC0->0xD0
677 memcpy(kirkHeader, prx+0x80, sizeof(kirkHeader)-0x10);
678 memcpy(kirkHeader+0x30, prx+0xC0, 0x10);
679 memcpy(kirkMetadata, prx+0xB0, sizeof(kirkMetadata));
680 memcpy(prxHeader, prx, sizeof(prxHeader));
681 }
682
decryptPRXType6683 void decrypt(int key)
684 {
685 kirk7(id, id, 0x60, key);
686 }
687
688 u8 tag[4];
689 u8 empty[0x38];
690 u8 ecdsaSignatureTail[0x20];
691 u8 id[0x10];
692 u8 sha1[0x14];
693 u8 kirkHeader[0x40];
694 u8 kirkMetadata[0x10];
695 u8 prxHeader[0x80];
696 };
697 static_assert(sizeof(PRXType6) == 0x150, "inconsistent size of PRX Type 6");
698
pspDecryptType0(const u8 * inbuf,u8 * outbuf,u32 size)699 static int pspDecryptType0(const u8 *inbuf, u8 *outbuf, u32 size)
700 {
701 INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
702 const auto decryptSize = *(s32_le*)&inbuf[0xB0];
703 const auto pti = GetTagInfo((u32)*(u32_le *)&inbuf[0xD0]);
704
705 if (!pti)
706 {
707 return -1;
708 }
709
710 // no need to expand seed, and no need to decrypt
711 // normally this would be a kirk7 op, but we have the seed pre-decrypted
712 std::array<u8, 0x90> xorbuf;
713 memcpy(xorbuf.data(), reinterpret_cast<const u8 *>(pti->key), xorbuf.size());
714
715 // construct the header format for a type 0 prx
716 PRXType0 type0(inbuf);
717
718 SHA_CTX ctx;
719 SHAInit(&ctx);
720 SHAUpdate(&ctx, xorbuf.data(), 0x14);
721 SHAUpdate(&ctx, type0.unused, sizeof(type0.unused));
722 SHAUpdate(&ctx, type0.kirkBlock, sizeof(type0.kirkBlock));
723 SHAUpdate(&ctx, type0.prxHeader, sizeof(type0.prxHeader));
724
725 u8 sha1[0x14];
726 SHAFinal(sha1, &ctx);
727
728 if (memcmp(sha1, type0.sha1, sizeof(sha1)) != 0)
729 {
730 return -3;
731 }
732
733 constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type0.prxHeader);
734 KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
735
736 if (outbuf != inbuf)
737 {
738 memcpy(outbuf, inbuf, size);
739 }
740
741 memcpy(header, type0.kirkBlock, sizeof(KIRK_CMD1_HEADER));
742 memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type0.prxHeader, sizeof(type0.prxHeader));
743 decryptKirkHeaderType0(reinterpret_cast<u8*>(header), type0.kirkBlock, xorbuf, pti->code);
744
745 if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
746 {
747 return -4;
748 }
749
750 return decryptSize;
751 }
752
pspDecryptType1(const u8 * inbuf,u8 * outbuf,u32 size)753 static int pspDecryptType1(const u8 *inbuf, u8 *outbuf, u32 size)
754 {
755 INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
756 const auto decryptSize = *(s32_le*)&inbuf[0xB0];
757 const auto pti = GetTagInfo((u32)*(u32_le *)&inbuf[0xD0]);
758
759 if (!pti)
760 {
761 return -1;
762 }
763
764 // no need to expand seed, and no need to decrypt
765 // normally this would be a kirk7 op, but we have the seed pre-decrypted
766 std::array<u8, 0x90> xorbuf;
767 memcpy(xorbuf.data(), reinterpret_cast<const u8 *>(pti->key), xorbuf.size());
768
769 // construct the header format for a type 1 prx
770 PRXType1 type1(inbuf);
771 type1.decrypt(pti->code);
772
773 SHA_CTX ctx;
774 SHAInit(&ctx);
775 SHAUpdate(&ctx, xorbuf.data(), 0x14);
776 SHAUpdate(&ctx, type1.unused, sizeof(type1.unused));
777 SHAUpdate(&ctx, type1.kirkBlock, sizeof(type1.kirkBlock));
778 SHAUpdate(&ctx, type1.prxHeader, sizeof(type1.prxHeader));
779
780 u8 sha1[0x14];
781 SHAFinal(sha1, &ctx);
782
783 if (memcmp(sha1, type1.sha1, sizeof(sha1)) != 0)
784 {
785 return -3;
786 }
787
788 constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type1.prxHeader);
789 KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
790
791 if (outbuf != inbuf)
792 {
793 memcpy(outbuf, inbuf, size);
794 }
795
796 memcpy(header, type1.kirkBlock, sizeof(KIRK_CMD1_HEADER));
797 memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type1.prxHeader, sizeof(type1.prxHeader));
798 decryptKirkHeaderType0(reinterpret_cast<u8*>(header), type1.kirkBlock, xorbuf, pti->code);
799
800 if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
801 {
802 return -4;
803 }
804
805 return decryptSize;
806 }
807
pspDecryptType2(const u8 * inbuf,u8 * outbuf,u32 size)808 static int pspDecryptType2(const u8 *inbuf, u8 *outbuf, u32 size)
809 {
810 INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
811 const auto decryptSize = *(s32_le*)&inbuf[0xB0];
812 const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);
813
814 if (!pti)
815 {
816 return -1;
817 }
818
819 // check if range is non-zero
820 if (std::any_of(inbuf+0xD4, inbuf+0xD4+0x58, [](u8 x) { return x != 0; }))
821 {
822 return -2;
823 }
824
825 // expand the seed into a xor buffer
826 auto xorbuf = expandSeed(pti->key, pti->code);
827
828 // construct the header format for a type 2 prx
829 PRXType2 type2(inbuf);
830 type2.decrypt(pti->code);
831
832 SHA_CTX ctx;
833 SHAInit(&ctx);
834 SHAUpdate(&ctx, type2.tag, sizeof(type2.tag));
835 SHAUpdate(&ctx, xorbuf.data(), 0x10);
836 SHAUpdate(&ctx, type2.empty, sizeof(type2.empty));
837 SHAUpdate(&ctx, type2.id, sizeof(type2.id));
838 SHAUpdate(&ctx, type2.kirkHeader, sizeof(type2.kirkHeader));
839 SHAUpdate(&ctx, type2.kirkMetadata, sizeof(type2.kirkMetadata));
840 SHAUpdate(&ctx, type2.prxHeader, sizeof(type2.prxHeader));
841
842 u8 sha1[0x14];
843 SHAFinal(sha1, &ctx);
844
845 if (memcmp(sha1, type2.sha1, sizeof(sha1)) != 0)
846 {
847 return -3;
848 }
849
850 constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type2.prxHeader);
851 KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
852
853 if (outbuf != inbuf)
854 {
855 memcpy(outbuf, inbuf, size);
856 }
857
858 memset(header, 0, sizeof(KIRK_CMD1_HEADER));
859 memcpy(reinterpret_cast<u8*>(&header->data_size), type2.kirkMetadata, sizeof(type2.kirkMetadata));
860 memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type2.prxHeader, sizeof(type2.prxHeader));
861 decryptKirkHeader(reinterpret_cast<u8*>(header), type2.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
862 header->mode = 1;
863
864 if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
865 {
866 return -4;
867 }
868
869 return decryptSize;
870 }
871
pspDecryptType5(const u8 * inbuf,u8 * outbuf,u32 size,const u8 * seed)872 static int pspDecryptType5(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)
873 {
874 INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
875 const auto decryptSize = *(s32_le*)&inbuf[0xB0];
876 const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);
877
878 if (!pti)
879 {
880 return -1;
881 }
882
883 // check if range is non-zero
884 if (std::any_of(inbuf+0xD4+1, inbuf+0xD4+0x58, [](u8 x) { return x != 0; }))
885 {
886 return -2;
887 }
888
889 // expand the seed into a xor buffer
890 auto xorbuf = expandSeed(pti->key, pti->code, seed);
891
892 // construct the header format for a type 2 prx
893 PRXType5 type5(inbuf);
894 type5.decrypt(pti->code, pti->seed, seed);
895
896 SHA_CTX ctx;
897 SHAInit(&ctx);
898 SHAUpdate(&ctx, type5.tag, sizeof(type5.tag));
899 SHAUpdate(&ctx, xorbuf.data(), 0x10);
900 SHAUpdate(&ctx, type5.empty, sizeof(type5.empty));
901 SHAUpdate(&ctx, type5.id, sizeof(type5.id));
902 SHAUpdate(&ctx, type5.kirkHeader, sizeof(type5.kirkHeader));
903 SHAUpdate(&ctx, type5.kirkMetadata, sizeof(type5.kirkMetadata));
904 SHAUpdate(&ctx, type5.prxHeader, sizeof(type5.prxHeader));
905
906 u8 sha1[0x14];
907 SHAFinal(sha1, &ctx);
908
909 if (memcmp(sha1, type5.sha1, sizeof(sha1)) != 0)
910 {
911 return -3;
912 }
913
914 constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_HEADER)-sizeof(type5.prxHeader);
915 KIRK_CMD1_HEADER *header = reinterpret_cast<KIRK_CMD1_HEADER *>(outbuf+offset);
916
917 if (outbuf != inbuf)
918 {
919 memcpy(outbuf, inbuf, size);
920 }
921
922 memset(header, 0, sizeof(KIRK_CMD1_HEADER));
923 memcpy(reinterpret_cast<u8*>(&header->data_size), type5.kirkMetadata, sizeof(type5.kirkMetadata));
924 memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_HEADER), type5.prxHeader, sizeof(type5.prxHeader));
925 decryptKirkHeader(reinterpret_cast<u8*>(header), type5.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
926 header->mode = 1;
927
928 if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
929 {
930 return -4;
931 }
932
933 return decryptSize;
934 }
935
pspDecryptType6(const u8 * inbuf,u8 * outbuf,u32 size)936 static int pspDecryptType6(const u8 *inbuf, u8 *outbuf, u32 size)
937 {
938 INFO_LOG(LOADER, "Decrypting tag %02X", (u32)*(u32_le *)&inbuf[0xD0]);
939 const auto decryptSize = *(s32_le*)&inbuf[0xB0];
940 const auto pti = GetTagInfo2((u32)*(u32_le *)&inbuf[0xD0]);
941
942 if (!pti)
943 {
944 return -1;
945 }
946
947 // check if range is non-zero
948 if (std::any_of(inbuf+0xD4, inbuf+0xD4+0x38, [](u8 x) { return x != 0; }))
949 {
950 return -2;
951 }
952
953 // expand the seed into a xor buffer
954 auto xorbuf = expandSeed(pti->key, pti->code);
955
956 // construct the header format for a type 2 prx
957 PRXType6 type6(inbuf);
958 type6.decrypt(pti->code);
959
960 SHA_CTX ctx;
961 SHAInit(&ctx);
962 SHAUpdate(&ctx, type6.tag, sizeof(type6.tag));
963 SHAUpdate(&ctx, xorbuf.data(), 0x10);
964 SHAUpdate(&ctx, type6.empty, sizeof(type6.empty));
965 SHAUpdate(&ctx, type6.ecdsaSignatureTail, sizeof(type6.ecdsaSignatureTail));
966 SHAUpdate(&ctx, type6.id, sizeof(type6.id));
967 SHAUpdate(&ctx, type6.kirkHeader, sizeof(type6.kirkHeader));
968 SHAUpdate(&ctx, type6.kirkMetadata, sizeof(type6.kirkMetadata));
969 SHAUpdate(&ctx, type6.prxHeader, sizeof(type6.prxHeader));
970
971 u8 sha1[0x14];
972 SHAFinal(sha1, &ctx);
973
974 if (memcmp(sha1, type6.sha1, sizeof(sha1)) != 0)
975 {
976 return -3;
977 }
978
979 constexpr auto offset = sizeof(PSP_Header)-sizeof(KIRK_CMD1_ECDSA_HEADER)-sizeof(type6.prxHeader);
980 KIRK_CMD1_ECDSA_HEADER *header = reinterpret_cast<KIRK_CMD1_ECDSA_HEADER *>(outbuf+offset);
981
982 if (outbuf != inbuf)
983 {
984 memcpy(outbuf, inbuf, size);
985 }
986
987 memset(header, 0, sizeof(KIRK_CMD1_ECDSA_HEADER));
988 memcpy(outbuf+offset+0x40, type6.ecdsaSignatureTail, sizeof(type6.ecdsaSignatureTail));
989 memcpy(reinterpret_cast<u8*>(&header->data_size), type6.kirkMetadata, sizeof(type6.kirkMetadata));
990 memcpy(reinterpret_cast<u8*>(header)+sizeof(KIRK_CMD1_ECDSA_HEADER), type6.prxHeader, sizeof(type6.prxHeader));
991 decryptKirkHeader(reinterpret_cast<u8*>(header), type6.kirkHeader, xorbuf.cbegin()+0x10, pti->code);
992 header->mode = 1;
993 header->ecdsa_hash = 1;
994
995 if (kirk_sceUtilsBufferCopyWithRange(outbuf, size, reinterpret_cast<const u8*>(header), size - offset, KIRK_CMD_DECRYPT_PRIVATE) != 0)
996 {
997 return -4;
998 }
999
1000 return decryptSize;
1001 }
1002
pspDecryptPRX(const u8 * inbuf,u8 * outbuf,u32 size,const u8 * seed)1003 int pspDecryptPRX(const u8 *inbuf, u8 *outbuf, u32 size, const u8 *seed)
1004 {
1005 kirk_init();
1006
1007 // this would be significantly better if we had a log of the tags
1008 // and their appropriate prx types
1009 // since we don't know the PRX type we attempt a decrypt using all
1010 auto res = pspDecryptType0(inbuf, outbuf, size);
1011
1012 if (res >= 0)
1013 return res;
1014
1015 res = pspDecryptType1(inbuf, outbuf, size);
1016
1017 if (res >= 0)
1018 return res;
1019
1020 res = pspDecryptType2(inbuf, outbuf, size);
1021
1022 if (res >= 0)
1023 return res;
1024
1025 res = pspDecryptType5(inbuf, outbuf, size, seed);
1026
1027 if (res >= 0)
1028 return res;
1029
1030 return pspDecryptType6(inbuf, outbuf, size);
1031 }
1032