sdk-core v2026.11.05
PS2 SDK - core tier (build-critical EE/IOP modules)
Loading...
Searching...
No Matches
libsecr.c
1#include <stdio.h>
2#include <string.h>
3#include <kernel.h>
4#include <sifrpc.h>
5#include <iopcontrol.h>
6
7#include "libsecr.h"
8#include "secrsif.h"
9
10static SifRpcClientData_t SifRpcClient01;
11static SifRpcClientData_t SifRpcClient02;
12static SifRpcClientData_t SifRpcClient03;
13static SifRpcClientData_t SifRpcClient04;
14static SifRpcClientData_t SifRpcClient05;
15static SifRpcClientData_t SifRpcClient06;
16static SifRpcClientData_t SifRpcClient07;
17
18static unsigned char RpcBuffer[0x1000] ALIGNED(64);
19
20#define _printf(args...) // printf(args)
21
22int SecrInit(void)
23{
24 if (HasIopRebootedSinceLastCall())
25 SecrDeinit();
26
27 sceSifInitRpc(0);
28
29 nopdelay();
30 while (sceSifBindRpc(&SifRpcClient01, 0x80000A01, 0) < 0 || SifRpcClient01.server == NULL) {
31 _printf("libsecr: bind failed\n");
32 }
33
34 nopdelay();
35 while (sceSifBindRpc(&SifRpcClient02, 0x80000A02, 0) < 0 || SifRpcClient02.server == NULL) {
36 _printf("libsecr: bind failed\n");
37 }
38
39 nopdelay();
40 while (sceSifBindRpc(&SifRpcClient03, 0x80000A03, 0) < 0 || SifRpcClient03.server == NULL) {
41 _printf("libsecr: bind failed\n");
42 }
43
44 nopdelay();
45 while (sceSifBindRpc(&SifRpcClient04, 0x80000A04, 0) < 0 || SifRpcClient04.server == NULL) {
46 _printf("libsecr: bind failed\n");
47 }
48
49 nopdelay();
50 while (sceSifBindRpc(&SifRpcClient05, 0x80000A05, 0) < 0 || SifRpcClient05.server == NULL) {
51 _printf("libsecr: bind failed\n");
52 }
53
54 nopdelay();
55 while (sceSifBindRpc(&SifRpcClient06, 0x80000A06, 0) < 0 || SifRpcClient06.server == NULL) {
56 _printf("libsecr: bind failed\n");
57 }
58
59 nopdelay();
60 while (sceSifBindRpc(&SifRpcClient07, 0x80000A07, 0) < 0 || SifRpcClient07.server == NULL) {
61 _printf("libsecr: bind failed\n");
62 }
63
64 return 1;
65}
66
67void SecrDeinit(void)
68{
69 memset(&SifRpcClient01, 0, sizeof(SifRpcClientData_t));
70 memset(&SifRpcClient02, 0, sizeof(SifRpcClientData_t));
71 memset(&SifRpcClient03, 0, sizeof(SifRpcClientData_t));
72 memset(&SifRpcClient04, 0, sizeof(SifRpcClientData_t));
73 memset(&SifRpcClient05, 0, sizeof(SifRpcClientData_t));
74 memset(&SifRpcClient06, 0, sizeof(SifRpcClientData_t));
75 memset(&SifRpcClient07, 0, sizeof(SifRpcClientData_t));
76}
77
78int SecrDownloadHeader(int port, int slot, void *buffer, SecrBitTable_t *BitTable, s32 *pSize)
79{
80 int result;
81
82 ((struct SecrSifDownloadHeaderParams *)RpcBuffer)->port = port;
83 ((struct SecrSifDownloadHeaderParams *)RpcBuffer)->slot = slot;
84 memcpy(((struct SecrSifDownloadHeaderParams *)RpcBuffer)->buffer, buffer, sizeof(((struct SecrSifDownloadHeaderParams *)RpcBuffer)->buffer));
85
86 if (sceSifCallRpc(&SifRpcClient01, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
87 _printf("sceSecrDownloadHeader: rpc error\n");
88 result = 0;
89 } else {
90 memcpy(BitTable, &((struct SecrSifDownloadHeaderParams *)RpcBuffer)->BitTable, ((struct SecrSifDownloadHeaderParams *)RpcBuffer)->size);
91 // BUG: pSize doesn't seem to be filled in within the Sony original.
92 if (pSize != NULL)
93 *pSize = ((struct SecrSifDownloadHeaderParams *)RpcBuffer)->size;
94 result = ((struct SecrSifDownloadHeaderParams *)RpcBuffer)->result;
95 }
96
97 return result;
98}
99
100int SecrDownloadBlock(void *src, unsigned int size)
101{
102 int result;
103
104 memcpy(((struct SecrSifDownloadBlockParams *)RpcBuffer)->buffer, src, sizeof(((struct SecrSifDownloadBlockParams *)RpcBuffer)->buffer));
105 ((struct SecrSifDownloadBlockParams *)RpcBuffer)->size = size;
106
107 if (sceSifCallRpc(&SifRpcClient02, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
108 _printf("sceSecrDownloadBlock: rpc error\n");
109 result = 0;
110 } else {
111 result = ((struct SecrSifDownloadBlockParams *)RpcBuffer)->result;
112 }
113
114 return result;
115}
116
117int SecrDownloadGetKbit(int port, int slot, void *kbit)
118{
119 int result;
120
121 ((struct SecrSifDownloadGetKbitParams *)RpcBuffer)->port = port;
122 ((struct SecrSifDownloadGetKbitParams *)RpcBuffer)->slot = slot;
123
124 if (sceSifCallRpc(&SifRpcClient03, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
125 _printf("sceSecrDownloadGetKbit: rpc error\n");
126 result = 0;
127 } else {
128 memcpy(kbit, ((struct SecrSifDownloadGetKbitParams *)RpcBuffer)->kbit, sizeof(((struct SecrSifDownloadGetKbitParams *)RpcBuffer)->kbit));
129 result = ((struct SecrSifDownloadGetKbitParams *)RpcBuffer)->result;
130 }
131
132 return result;
133}
134
135int SecrDownloadGetKc(int port, int slot, void *kc)
136{
137 int result;
138
139 ((struct SecrSifDownloadGetKcParams *)RpcBuffer)->port = port;
140 ((struct SecrSifDownloadGetKcParams *)RpcBuffer)->slot = slot;
141
142 if (sceSifCallRpc(&SifRpcClient04, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
143 _printf("sceSecrDownloadGetKc: rpc error\n");
144 result = 0;
145 } else {
146 memcpy(kc, ((struct SecrSifDownloadGetKcParams *)RpcBuffer)->kc, sizeof(((struct SecrSifDownloadGetKcParams *)RpcBuffer)->kc));
147 result = ((struct SecrSifDownloadGetKcParams *)RpcBuffer)->result;
148 }
149
150 return result;
151}
152
153int SecrDownloadGetICVPS2(void *icvps2)
154{
155 int result;
156
157 if (sceSifCallRpc(&SifRpcClient05, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
158 _printf("sceSecrDownloadGetICVPS2: rpc error\n");
159 result = 0;
160 } else {
161 memcpy(icvps2, ((struct SecrSifDownloadGetIcvps2Params *)RpcBuffer)->icvps2, sizeof(((struct SecrSifDownloadGetIcvps2Params *)RpcBuffer)->icvps2));
162 result = ((struct SecrSifDownloadGetIcvps2Params *)RpcBuffer)->result;
163 }
164
165 return result;
166}
167
168int SecrDiskBootHeader(void *buffer, SecrBitTable_t *BitTable, s32 *pSize)
169{
170 int result;
171
172 memcpy(((struct SecrSifDiskBootHeaderParams *)RpcBuffer)->buffer, buffer, sizeof(((struct SecrSifDiskBootHeaderParams *)RpcBuffer)->buffer));
173
174 if (sceSifCallRpc(&SifRpcClient06, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
175 _printf("sceSecrDiskBootHeader: rpc error\n");
176 result = 0;
177 } else {
178 memcpy(BitTable, &((struct SecrSifDiskBootHeaderParams *)RpcBuffer)->BitTable, ((struct SecrSifDiskBootHeaderParams *)RpcBuffer)->size);
179 // BUG: pSize doesn't seem to be filled in within the Sony original.
180 if (pSize != NULL)
181 *pSize = ((struct SecrSifDiskBootHeaderParams *)RpcBuffer)->size;
182 result = ((struct SecrSifDiskBootHeaderParams *)RpcBuffer)->result;
183 }
184
185 return result;
186}
187
188int SecrDiskBootBlock(void *src, void *dst, unsigned int size)
189{
190 int result;
191
192 memcpy(((struct SecrSifDiskBootBlockParams *)RpcBuffer)->source, src, size);
193 ((struct SecrSifDiskBootBlockParams *)RpcBuffer)->size = size;
194
195 if (sceSifCallRpc(&SifRpcClient07, 1, 0, RpcBuffer, sizeof(RpcBuffer), RpcBuffer, sizeof(RpcBuffer), NULL, NULL) < 0) {
196 _printf("sceSecrDiskBootBlock: rpc error\n");
197 result = 0;
198 } else {
199 result = ((struct SecrSifDiskBootBlockParams *)RpcBuffer)->result;
200 memcpy(dst, ((struct SecrSifDiskBootBlockParams *)RpcBuffer)->destination, size);
201 }
202
203 return result;
204}
205
206static unsigned short int GetHeaderLength(const void *buffer)
207{
208 return ((const SecrKELFHeader_t *)buffer)->KELF_header_size;
209}
210
211static void store_kbit(void *buffer, const void *kbit)
212{
213 const SecrKELFHeader_t *header = buffer;
214 int offset = 0x20, kbit_offset;
215
216 if (header->BIT_count > 0)
217 offset += header->BIT_count * sizeof(SecrBitBlockData_t);
218 if (((header->flags) & 1) != 0)
219 offset += ((unsigned char *)buffer)[offset] + 1;
220 if (((header->flags) & 0xF000) == 0)
221 offset += 8;
222
223 kbit_offset = (unsigned int)buffer + offset;
224 memcpy((void *)kbit_offset, kbit, 16);
225 _printf("kbit_offset: %d\n", kbit_offset);
226}
227
228static void store_kc(void *buffer, const void *kc)
229{
230 const SecrKELFHeader_t *header = buffer;
231 int offset = 0x20, kc_offset;
232
233 if (header->BIT_count > 0)
234 offset += header->BIT_count * sizeof(SecrBitBlockData_t);
235 if (((header->flags) & 1) != 0)
236 offset += ((unsigned char *)buffer)[offset] + 1;
237 if (((header->flags) & 0xF000) == 0)
238 offset += 8;
239
240 kc_offset = (unsigned int)buffer + offset + 0x10; // Goes after Kbit.
241 memcpy((void *)kc_offset, kc, 16);
242 _printf("kc_offset: %d\n", kc_offset);
243}
244
245static int Uses_ICVPS2(const void *buffer)
246{
247 return (((const SecrKELFHeader_t *)buffer)->flags >> 1 & 1);
248}
249
250static void store_icvps2(void *buffer, const void *icvps2)
251{
252 unsigned int pICVPS2;
253
254 pICVPS2 = (unsigned int)buffer + ((SecrKELFHeader_t *)buffer)->KELF_header_size - 8;
255 memcpy((void *)pICVPS2, icvps2, 8);
256 _printf("icvps2_offset %d\n", pICVPS2);
257}
258
259static unsigned int get_BitTableOffset(const void *buffer)
260{
261 const SecrKELFHeader_t *header = buffer;
262 int offset = sizeof(SecrKELFHeader_t);
263
264 if (header->BIT_count > 0)
265 offset += header->BIT_count * sizeof(SecrBitBlockData_t); // They used a loop for this. D:
266 if ((header->flags & 1) != 0)
267 offset += ((const unsigned char *)buffer)[offset] + 1;
268 if ((header->flags & 0xF000) == 0)
269 offset += 8;
270 return (offset + 0x20); // Goes after Kbit and Kc.
271}
272
273void *SecrDownloadFile(int port, int slot, void *buffer)
274{
275 SecrBitTable_t BitTableData;
276 void *result;
277
278 _printf("SecrDownloadFile start\n");
279 if (SecrDownloadHeader(port, slot, buffer, &BitTableData, NULL) != 0) {
280 unsigned char kbit[16], kcontent[16];
281
282 if (BitTableData.header.block_count > 0) {
283 unsigned int offset, i;
284
285 offset = BitTableData.header.headersize;
286 for (i = 0; i < BitTableData.header.block_count; i++) {
287 if (BitTableData.blocks[i].flags & 2) {
288 if (!SecrDownloadBlock((void *)((unsigned int)buffer + offset), BitTableData.blocks[i].size)) {
289 _printf("SecrDownloadFile: failed\n");
290 return NULL;
291 }
292 }
293 offset += BitTableData.blocks[i].size;
294 }
295 }
296
297 if (SecrDownloadGetKbit(port, slot, kbit) == 0) {
298 _printf("SecrDownloadFile: Cannot get kbit\n");
299 return NULL;
300 }
301 if (SecrDownloadGetKc(port, slot, kcontent) == 0) {
302 _printf("SecrDownloadFile: Cannot get kc\n");
303 return NULL;
304 }
305
306 store_kbit(buffer, kbit);
307 store_kc(buffer, kcontent);
308
309 if (Uses_ICVPS2(buffer) == 1) {
310 unsigned char icvps2[8];
311
312 if (SecrDownloadGetICVPS2(icvps2) == 0) {
313 _printf("SecrDownloadFile: Cannot get icvps2\n");
314 return NULL;
315 }
316
317 store_icvps2(buffer, icvps2);
318 }
319
320 result = buffer;
321 } else {
322 _printf("SecrDownloadFile: Cannot encrypt header\n");
323 return NULL;
324 }
325
326 _printf("SecrDownloadFile complete\n");
327
328 return result;
329}
330
331void *SecrDiskBootFile(void *buffer)
332{
333 void *result;
334 SecrBitTable_t *BitTableData;
335
336 BitTableData = (SecrBitTable_t *)((unsigned int)buffer + get_BitTableOffset(buffer));
337 if (SecrDiskBootHeader(buffer, BitTableData, NULL)) {
338 if (BitTableData->header.block_count > 0) {
339 unsigned int offset, i;
340
341 offset = BitTableData->header.headersize;
342 for (i = 0; i < BitTableData->header.block_count; i++) {
343 if (BitTableData->blocks[i].flags & 3) {
344 if (!SecrDiskBootBlock((void *)((unsigned int)buffer + offset), (void *)((unsigned int)buffer + offset), BitTableData->blocks[i].size)) {
345 _printf("SecrDiskBootFile: failed\n");
346 return NULL;
347 }
348 }
349 offset += BitTableData->blocks[i].size;
350 }
351 }
352
353 result = (void *)((unsigned int)buffer + GetHeaderLength(buffer));
354 } else {
355 _printf("sceSecrDiskBootFile: Cannot decrypt header\n");
356 result = NULL;
357 }
358
359 return result;
360}
struct KELF_Header SecrKELFHeader_t
struct SecrBitTable SecrBitTable_t
struct SecrBitBlockData SecrBitBlockData_t
SecrBitBlockData_t blocks[63]