PS2SDK
PS2 Homebrew Libraries
Loading...
Searching...
No Matches
secrman.c
1#include <loadcore.h>
2#include <ioman.h>
3#include <modload.h>
4#include <stdio.h>
5#include <sysclib.h>
6#include <irx.h>
7#include <sio2man.h>
8
9#include "secrman.h"
10
11#include "main.h"
12#include "MechaAuth.h"
13#include "CardAuth.h"
14#include "keyman.h"
15
16// Based on the module from DVD Player Installer 2.14
17
18#ifdef BUILDING_ARCADE_SECRMAN
19#define CARD_AUTH_KEY_CHANGE_CMDNUM 3 // cmd number for `card_auth_key_change()`. arcade SECRMAN uses `3` for this
20#define MODNAME "secrman_for_arcade"
21#else
22#define CARD_AUTH_KEY_CHANGE_CMDNUM 1 // cmd number for `card_auth_key_change()`. arcade SECRMAN uses `3` for this
23#define MODNAME "secrman_special"
24#endif
25
26IRX_ID(MODNAME, 1, 4);
27
28#ifdef DEX_SUPPORT
29int IsDEX;
30#endif
31
32extern struct irx_export_table _exp_secrman;
33
34#if 0
35static void _printf(const char *format, ...);
36#endif
37
39{
41 SecrBitBlockData_t *blocks;
42 unsigned int padding; // Doesn't seem to be used.
43};
44
45static loadfile_elf_load_proc_callback_t loadfile_elf_load_proc; // 0x00003d20
46static loadfile_check_valid_ee_elf_callback_t loadfile_check_valid_ee_elf; // 0x00003d24
47static loadfile_elf_get_program_header_callback_t loadfile_elf_get_program_header; // 0x00003d28
48static loadfile_elf_load_alloc_buffer_from_heap_callback_t loadfile_elf_load_alloc_buffer_from_heap; // 0x00003d2c
49static loadfile_elf_load_dealloc_buffer_from_heap_callback_t loadfile_elf_load_dealloc_buffer_from_heap; // 0x00003d30
50
51// Function prototypes.
52static int card_decrypt(int port, int slot, void *buffer);
53static int func_00000bfc(void *dest, unsigned int size);
54static int func_00002eb0(struct ModloadBitTableDescriptor *ModloadBitTableDescriptor, int fd, int port, int slot, int device);
55static int secrman_loadfile_read_callback_common(int fd, loadfile_allocate_handler_struct_t *allocate_info, const struct ModloadBitTableDescriptor *ModloadBitTableDescriptor, int (*DecryptBlockFunction)(void *src, void *dest, unsigned int size));
56static int secrman_loadfile_read_callback_card(int fd, loadfile_allocate_handler_struct_t *allocate_info, void *read_callback_userdata);
57static int secrman_load_kelf_common(loadfile_allocate_handler_struct_t *allocate_info, loadfile_file_load_handler_struct_t *flhs, int port, int slot, int *result_out, int *result_module_out, int device, loadfile_read_chunk_callback_t decrypt);
58static int secrman_load_kelf_from_card(loadfile_allocate_handler_struct_t *allocate_info, loadfile_file_load_handler_struct_t *flhs, int port, int slot, int *result_out, int *result_module_out);
59static int secrman_loadfile_read_callback_disk(int fd, loadfile_allocate_handler_struct_t *allocate_info, void *read_callback_userdata);
60static int secrman_load_kelf_from_disk(loadfile_allocate_handler_struct_t *allocate_info, loadfile_file_load_handler_struct_t *flhs, int *result_out, int *result_module_out);
61static void SecrGetLoadfileCallbacks(SetLoadfileCallbacks_struct_t *unknown);
62static void RegisterSecrCallbackHandlers(void);
63static int card_encrypt(int port, int slot, void *buffer);
64static unsigned short int GetHeaderLength(const void *buffer);
65static int secr_set_header(int mode, int cnum, int arg2, void *buffer);
66static int Read_BIT(SecrBitTable_t *BitTable);
67static unsigned int get_BitTableOffset(const void *buffer);
68static int func_00000b5c(const void *block, unsigned int size);
69
71static int scePreEncryptKbit(void *kbit);
72
74static int scePreEncryptKc(void *kc);
75static int func_00000d14(void *icvps2);
76static int Uses_ICVPS2(const void *buffer);
77
78// 0x00000000
79#if 0
80static void _printf(const char *format, ...){
81
82}
83#endif
84
85// 0x0000077c
86static int card_decrypt(int port, int slot, void *buffer)
87{
88 if (GetMcCommandHandler() == NULL) {
89 return 0;
90 }
91
92 _printf("card decrypt start\n");
93
94 if (card_auth(port, slot, 0xF1, 0x40) == 0) {
95 return 0;
96 }
97
98 _printf("card decrypt 0x40\n");
99
100 if (card_auth_write(port, slot, buffer, 0xF1, 0x41) == 0) {
101 return 0;
102 }
103
104 _printf("card decrypt 0x41\n");
105
106 if (card_auth(port, slot, 0xF1, 0x42) == 0) {
107 return 0;
108 }
109
110 _printf("card decrypt 0x42\n");
111
112 if (card_auth_read(port, slot, buffer, 0xF1, 0x43) == 0) {
113 return 0;
114 }
115
116 _printf("card decrypt 0x43\n");
117
118 return 1;
119}
120
121// 0x00000d34 - export #08
122int SecrCardBootHeader(int port, int slot, void *buffer, SecrBitTable_t *BitTable, s32 *pSize)
123{
124 unsigned char Kbit[16], Kc[16];
125 int cnum;
126 int BitTableSize;
127
128 if (GetMcCommandHandler() == NULL) {
129 _printf("mcCommand isn't assigned\n");
130 return 0;
131 }
132
133 get_Kbit(buffer, Kbit);
134 get_Kc(buffer, Kc);
135
136 if (card_decrypt(port, slot, Kbit) == 0) {
137 return 0;
138 }
139
140 if (card_decrypt(port, slot, &Kbit[8]) == 0) {
141 return 0;
142 }
143
144 if (card_decrypt(port, slot, Kc) == 0) {
145 return 0;
146 }
147
148 if (card_decrypt(port, slot, &Kc[8]) == 0) {
149 return 0;
150 }
151
152 store_kc(buffer, Kc);
153 store_kbit(buffer, Kbit);
154
155 if ((cnum = McDeviceIDToCNum(port, slot)) < 0) {
156 return 0;
157 }
158
159 if (secr_set_header(1, cnum, 0, buffer) == 0) {
160 _printf("Set Header failed\n");
161 return 0;
162 }
163
164 if ((BitTableSize = Read_BIT(BitTable)) == 0) {
165 _printf("Cannot read BIT\n");
166 return 0;
167 }
168
169 if (pSize != NULL) {
170 *pSize = BitTableSize;
171 }
172
173 return 1;
174}
175
176
177
178// 0x00000bfc
179static int func_00000bfc(void *dest, unsigned int size)
180{
181 if (func_00001c98(size) == 0) {
182 return 0;
183 }
184 /*
185 There was something like this here that doesn't make sense (instead of just the simple loop below):
186 if(size>0){
187 if(size<0) size+=0xF
188
189 while(size>0){
190 ...
191 }
192 }
193 */
194 while (size > 0) {
195 if (size >= 16) { // if(size>>4!=0)
196 if (func_00001b00(dest, 0x10) == 0) {
197 return 0;
198 }
199 size -= 0x10;
200 dest = (void *)((u8 *)dest + 0x10);
201 } else {
202 if (func_00001b00(dest, size) == 0) {
203 return 0;
204 }
205 size = 0;
206 }
207 }
208
209 return 1;
210}
211
212// 0x00000e90 - export #09
213int SecrCardBootBlock(void *src, void *dest, unsigned int size)
214{
215 if (func_00000b5c(src, size) == 0) {
216 return 0;
217 }
218
219 if (func_00000bfc(dest, size) == 0) {
220 return 0;
221 }
222
223 return 1;
224}
225
226// 0x000011b4 - export #10
227void *SecrCardBootFile(int port, int slot, void *buffer)
228{
229 SecrBitTable_t *BitTableData;
230 unsigned int offset, i;
231
232 BitTableData = (SecrBitTable_t *)((u8 *)buffer + get_BitTableOffset(buffer));
233 if (SecrCardBootHeader(port, slot, buffer, BitTableData, NULL) == 0) {
234 _printf("SecrCardBootFile: Cannot decrypt header\n");
235 return NULL;
236 }
237
238 offset = BitTableData->header.headersize;
239 for (i = 0; i < BitTableData->header.block_count; i++) {
240 if (BitTableData->blocks[i].flags & 3) {
241 if (!SecrCardBootBlock((void *)((u8 *)buffer + offset), (void *)((u8 *)buffer + offset), BitTableData->blocks[i].size)) {
242 _printf("SecrCardBootFile: failed\n");
243 return NULL;
244 }
245 }
246 offset += BitTableData->blocks[i].size;
247 }
248
249 return (void *)((u8 *)buffer + GetHeaderLength(buffer));
250}
251
252// 0x000010dc - export #11
253int SecrDiskBootHeader(void *buffer, SecrBitTable_t *BitTable, s32 *pSize)
254{
255 int BitTableSize;
256
257 if (secr_set_header(0, 0, 0, buffer) == 0) {
258 _printf("Set Header failed\n");
259 return 0;
260 }
261
262 if ((BitTableSize = Read_BIT(BitTable)) == 0) {
263 _printf("Cannot read BIT\n");
264 return 0;
265 }
266
267 if (pSize != NULL) {
268 *pSize = BitTableSize;
269 }
270
271 return 1;
272}
273
274// 0x00001164 - export #12
275int SecrDiskBootBlock(void *src, void *dest, unsigned int size)
276{
277 if (func_00000b5c(src, size) == 0) {
278 return 0;
279 }
280 if (func_00000bfc(dest, size) == 0) {
281 return 0;
282 }
283
284 return 1;
285}
286
287// 0x00001474 - export #13
288void *SecrDiskBootFile(void *buffer)
289{
290 SecrBitTable_t *BitTableData;
291 unsigned int offset, i;
292
293 BitTableData = (SecrBitTable_t *)((u8 *)buffer + get_BitTableOffset(buffer));
294 if (SecrDiskBootHeader(buffer, BitTableData, NULL) == 0) {
295 _printf("SecrDiskBootFile: Cannot decrypt header\n");
296 return NULL;
297 }
298
299 offset = BitTableData->header.headersize;
300 for (i = 0; i < BitTableData->header.block_count; i++) {
301 if (BitTableData->blocks[i].flags & 3) {
302 if (!SecrDiskBootBlock((void *)((u8 *)buffer + offset), (void *)((u8 *)buffer + offset), BitTableData->blocks[i].size)) {
303 _printf("SecrDiskBootFile: failed\n");
304 return NULL;
305 }
306 }
307 offset += BitTableData->blocks[i].size;
308 }
309
310 return (void *)((u8 *)buffer + GetHeaderLength(buffer));
311}
312
313// 0x00002eb0
314static int func_00002eb0(struct ModloadBitTableDescriptor *ModloadBitTableDescriptor, int fd, int port, int slot, int device)
315{
316 int header_result;
317 SecrKELFHeader_t header;
318 SecrBitTable_t *BitTableData;
319 unsigned short int HeaderLength;
320 void *HeaderBuffer;
321
322 if (lseek(fd, 0, SEEK_SET) != 0) {
323 return -204;
324 }
325
326 if (read(fd, &header, sizeof(SecrKELFHeader_t)) != sizeof(SecrKELFHeader_t)) {
327 return -204;
328 }
329
330 HeaderLength = GetHeaderLength(&header);
331 if ((HeaderBuffer = loadfile_elf_load_alloc_buffer_from_heap(HeaderLength)) == NULL) {
332 return -400;
333 }
334
335 if (lseek(fd, 0, SEEK_SET) != 0) {
336 loadfile_elf_load_dealloc_buffer_from_heap(HeaderBuffer);
337 return -201;
338 }
339
340 if (read(fd, HeaderBuffer, HeaderLength) != HeaderLength) {
341 loadfile_elf_load_dealloc_buffer_from_heap(HeaderBuffer);
342 return -204;
343 }
344
345 BitTableData = (SecrBitTable_t *)((unsigned int)HeaderBuffer + get_BitTableOffset(HeaderBuffer));
346
347 if (device == 0) {
348 header_result = SecrCardBootHeader(port, slot, HeaderBuffer, BitTableData, NULL);
349 } else if (device == 1) {
350 header_result = SecrDiskBootHeader(HeaderBuffer, BitTableData, NULL);
351 } else {
352 return -1;
353 }
354
355 if (header_result != 1) {
356 loadfile_elf_load_dealloc_buffer_from_heap(HeaderBuffer);
357 return -201;
358 }
359
360 memcpy(&ModloadBitTableDescriptor->header, &BitTableData->header, sizeof(ModloadBitTableDescriptor->header));
361 ModloadBitTableDescriptor->blocks = BitTableData->blocks;
362
363 return 0;
364}
365
366/* 0x0000306c - Reads a block of encrypted data and decrypts it.
367 This is one really irritating function. Since nobody has ever completed and released a disassembly of MODLOAD, there were a whole load of structures that I had to figure out by cross-referencing LOADFILE, MODLOAD and SECRMAN. */
368static int secrman_loadfile_read_callback_common(int fd, loadfile_allocate_handler_struct_t *allocate_info, const struct ModloadBitTableDescriptor *ModloadBitTableDescriptor, int (*DecryptBlockFunction)(void *src, void *dest, unsigned int size))
369{
370 unsigned int i, PayloadLength, excess;
372 unsigned int ExcessBlockNum;
373 void *BlockExcessRegionPtr;
374
375#if 0
376 printf( "secrman_loadfile_read_callback_common:\n"
377 "\tModloadUnk2->ring_buffer_index:\t%d\n"
378 "\tModloadUnk2->read_buffer_offset:\t%d\n"
379 "\tModloadUnk2->read_buffer_length:\t%d\n", allocate_info->ring_buffer_index, allocate_info->read_buffer_offset, allocate_info->read_buffer_length);
380#endif
381
382 entry = &allocate_info->ring_buffer_contents[allocate_info->ring_buffer_index];
383 entry->buffer_offset = allocate_info->read_buffer_offset;
384 for (i = 0, PayloadLength = 0; i < ModloadBitTableDescriptor->header.block_count; PayloadLength += ModloadBitTableDescriptor->blocks[i].size, i++) {
385 if (allocate_info->read_buffer_offset < PayloadLength + ModloadBitTableDescriptor->blocks[i].size) {
386 break;
387 }
388 }
389
390 // 0x000030fc - Partially decrypting blocks is not possible.
391 if ((((excess = PayloadLength - entry->buffer_offset) != 0) && (ModloadBitTableDescriptor->blocks[i].flags & 3)) != 0) {
392#if 0
393 printf("WIP function 0x0000306c: can't partially decrypt block.\n");
394#endif
395 return -201;
396 }
397
398 ExcessBlockNum = i;
399 BlockExcessRegionPtr = (void *)((u8 *)(entry->buffer_base) + excess);
400
401 for (; i < ModloadBitTableDescriptor->header.block_count; excess += ModloadBitTableDescriptor->blocks[i].size, i++) {
402 // 0x00003140
403 if (ModloadBitTableDescriptor->blocks[i].size + excess >= allocate_info->read_buffer_length) {
404 if (!(ModloadBitTableDescriptor->blocks[i].flags & 3)) {
405 excess = allocate_info->read_buffer_length;
406 }
407
408 break;
409 }
410 }
411
412 if (((unsigned int)read(fd, entry->buffer_base, excess)) != excess) {
413 return -204;
414 }
415
416 allocate_info->read_buffer_offset += excess;
417
418 for (; ExcessBlockNum < i; BlockExcessRegionPtr = (void *)((u8 *)BlockExcessRegionPtr + ModloadBitTableDescriptor->blocks[ExcessBlockNum].size), ExcessBlockNum++) {
419 if (ModloadBitTableDescriptor->blocks[ExcessBlockNum].flags & 3) {
420 // 0x000031d8
421 if (DecryptBlockFunction(BlockExcessRegionPtr, BlockExcessRegionPtr, ModloadBitTableDescriptor->blocks[ExcessBlockNum].size) != 1) {
422 return -201;
423 }
424 }
425 }
426
427 return 0;
428}
429
430// 0x00003364
431static int secrman_loadfile_read_callback_card(int fd, loadfile_allocate_handler_struct_t *allocate_info, void *read_callback_userdata)
432{
433 return secrman_loadfile_read_callback_common(fd, allocate_info, (const struct ModloadBitTableDescriptor *)read_callback_userdata, &SecrCardBootBlock);
434}
435
436// 0x00003230
437static int secrman_load_kelf_common(loadfile_allocate_handler_struct_t *allocate_info, loadfile_file_load_handler_struct_t *flhs, int port, int slot, int *result_out, int *result_module_out, int device, loadfile_read_chunk_callback_t decrypt)
438{
440
441 if (func_00002eb0(&ModloadBitTableDescriptor, flhs->fd, port, slot, device) != 0) {
442 return -201;
443 }
444
445 if (((u32)lseek(flhs->fd, ModloadBitTableDescriptor.header.headersize, SEEK_SET)) != ModloadBitTableDescriptor.header.headersize) {
446 return -204;
447 }
448
449 if (decrypt(flhs->fd, allocate_info, &ModloadBitTableDescriptor) != 0) {
450 return -204;
451 }
452
453 if (loadfile_check_valid_ee_elf(allocate_info, flhs) != 0) {
454 printf("don't get elf header\n");
455 return -201;
456 }
457
458 if (loadfile_elf_get_program_header(allocate_info, flhs) != 0) {
459 printf("don't get program header\n");
460 return -201;
461 }
462
463 if (loadfile_elf_load_proc(allocate_info, flhs, &ModloadBitTableDescriptor, decrypt) != 0) {
464 printf("load elf error\n");
465 return -201;
466 }
467
468 // 0x00003318
469 *result_out = flhs->elf_header.e_entry;
470 *result_module_out = 0;
471
472 return 0;
473}
474
475// 0x0000338c
476static int secrman_load_kelf_from_card(loadfile_allocate_handler_struct_t *allocate_info, loadfile_file_load_handler_struct_t *flhs, int port, int slot, int *result_out, int *result_module_out)
477{
478 return secrman_load_kelf_common(allocate_info, flhs, port, slot, result_out, result_module_out, 0, &secrman_loadfile_read_callback_card);
479}
480
481// 0x000033c8
482static int secrman_loadfile_read_callback_disk(int fd, loadfile_allocate_handler_struct_t *allocate_info, void *read_callback_userdata)
483{
484 return secrman_loadfile_read_callback_common(fd, allocate_info, (const struct ModloadBitTableDescriptor *)read_callback_userdata, &SecrDiskBootBlock);
485}
486
487// 0x000033f0
488static int secrman_load_kelf_from_disk(loadfile_allocate_handler_struct_t *allocate_info, loadfile_file_load_handler_struct_t *flhs, int *result_out, int *result_module_out)
489{
490 return secrman_load_kelf_common(allocate_info, flhs, 0, 0, result_out, result_module_out, 1, &secrman_loadfile_read_callback_disk);
491}
492
493// 0x00003430
494static void SecrGetLoadfileCallbacks(SetLoadfileCallbacks_struct_t *callbackinfo)
495{
496 loadfile_elf_load_proc = callbackinfo->elf_load_proc;
497 loadfile_check_valid_ee_elf = callbackinfo->check_valid_ee_elf;
498 loadfile_elf_get_program_header = callbackinfo->elf_get_program_header;
499 loadfile_elf_load_alloc_buffer_from_heap = callbackinfo->elf_load_alloc_buffer_from_heap;
500 loadfile_elf_load_dealloc_buffer_from_heap = callbackinfo->elf_load_dealloc_buffer_from_heap;
501
502 callbackinfo->load_kelf_from_card = &secrman_load_kelf_from_card;
503 callbackinfo->load_kelf_from_disk = &secrman_load_kelf_from_disk;
504}
505
506// 0x0000348c
507static void RegisterSecrCallbackHandlers(void)
508{
509 SetSecrmanCallbacks(&SecrCardBootFile, &SecrDiskBootFile, &SecrGetLoadfileCallbacks);
510}
511
512// 0x00000018
513int _start(int argc, char *argv[])
514{
515#ifdef DEX_SUPPORT
516 int fd;
517 char type;
518#endif
519
520 (void)argc;
521 (void)argv;
522
523#ifdef DEX_SUPPORT
524 fd = open("rom0:ROMVER", O_RDONLY);
525 lseek(fd, 5, SEEK_SET);
526 read(fd, &type, 1);
527 close(fd);
528
529 IsDEX = type == 'D';
530#endif
531
532 if (RegisterLibraryEntries(&_exp_secrman) != 0) {
533 return MODULE_NO_RESIDENT_END;
534 }
535
536 ResetMcHandlers();
537 RegisterSecrCallbackHandlers();
538
539 return MODULE_RESIDENT_END;
540}
541
542// 0x0000005c
543int _exit(int argc, char *argv[])
544{
545 (void)argc;
546 (void)argv;
547
548 return MODULE_NO_RESIDENT_END;
549}
550
551// 0x00000064 - export #04
552void SecrSetMcCommandHandler(McCommandHandler_t handler)
553{
554 SetMcCommandHandler(handler);
555}
556
557// 0x00000084 - export #05
558void SecrSetMcDevIDHandler(McDevIDHandler_t handler)
559{
560 SetMcDevIDHandler(handler);
561}
562
563// 0x000000a4 - export #06
564// This is the most badass function in the whole file. Not only was it difficult to see whether I got all the pointers right, it invokes many functions, making it a difficult one to debug. I tried to make the buffer names the same as within the FMCB PS3MCA bundle's Card_Authentificate() function.
565int SecrAuthCard(int port, int slot, int cnum)
566{
567 unsigned char MechaChallenge2[8], CardIV[8], CardMaterial[8], CardNonce[8], MechaChallenge1[8], MechaChallenge3[8], CardResponse1[8], CardResponse2[8], CardResponse3[8];
568
569 if (GetMcCommandHandler() == NULL) {
570 _printf("mcCommand isn't assigned\n");
571 return 0;
572 }
573
574 _printf("SecrAuthCard start\n");
575
576 memset(MechaChallenge1, 0, sizeof(MechaChallenge1));
577
578 if (card_auth_60(port, slot) == 0) {
579 return 0;
580 }
581
582 _printf("card auth 0x60\n");
583
584 if (mechacon_auth_80(cnum) == 0) {
585 return 0;
586 }
587
588 _printf("mechacon auth 0x80\n");
589
590 /* sp193: The normal secrman_for_dex module does not have this step. With this step, card authentication does not work on a DEX.
591 On a CEX, it appears that card authentication still works without this step, but I don't know whether there are any side-effects.
592
593 El_isra: arcade SECRMAN uses CMD number 3 here, unlike our homebrew one, that uses 1.
594 */
595 if ((
596#ifdef DEX_SUPPORT
597 IsDEX ||
598#endif
599 card_auth_key_change(port, slot, CARD_AUTH_KEY_CHANGE_CMDNUM)) == 0) {
600 card_auth_60(port, slot);
601 return 0;
602 }
603
604 _printf("card auth key change\n");
605
606 if (card_auth(port, slot, 0xF0, 0x00) == 0) {
607 card_auth_60(port, slot);
608 return 0;
609 }
610
611 _printf("card auth 0x00\n");
612
613 if (mechacon_auth_81(cnum) == 0) {
614 card_auth_60(port, slot);
615 return 0;
616 }
617
618 _printf("mechacon auth 0x81\n");
619
620 if (card_auth_read(port, slot, CardIV, 0xF0, 0x01) == 0) {
621 goto Error2_end;
622 }
623
624 _printf("card auth 0x01\n");
625
626 if (card_auth_read(port, slot, CardMaterial, 0xF0, 0x02) == 0) {
627 goto Error2_end;
628 }
629
630 _printf("card auth 0x02\n");
631
632 if (mechacon_auth_82(CardIV, CardMaterial) == 0) {
633 goto Error2_end;
634 }
635
636 _printf("mechacon auth 0x82\n");
637
638 if (card_auth(port, slot, 0xF0, 0x03) == 0) {
639 goto Error2_end;
640 }
641
642 _printf("card auth 0x03\n");
643
644 if (card_auth_read(port, slot, CardNonce, 0xF0, 0x04) == 0) {
645 goto Error2_end;
646 }
647
648 _printf("card auth 0x04\n");
649
650 if (mechacon_auth_83(CardNonce) == 0) {
651 goto Error2_end;
652 }
653
654 _printf("mechacon auth 0x83\n");
655
656 if (card_auth(port, slot, 0xF0, 0x05) == 0) {
657 goto Error2_end;
658 }
659
660 _printf("card auth 0x05\n");
661
662 if (pol_cal_cmplt() == 0) {
663 goto Error2_end;
664 }
665
666 _printf("mechacon auth 0x8f\n");
667
668 if (mechacon_auth_84(MechaChallenge1, MechaChallenge2) == 0) {
669 goto Error2_end;
670 }
671
672 _printf("mechacon auth 0x84\n");
673
674 if (mechacon_auth_85(&MechaChallenge2[4], MechaChallenge3) == 0) {
675 goto Error2_end;
676 }
677
678 _printf("mechacon auth 0x85\n");
679
680 if (card_auth_write(port, slot, MechaChallenge3, 0xF0, 0x06) == 0) {
681 goto Error2_end;
682 }
683
684 _printf("card auth 0x06\n");
685
686 if (card_auth_write(port, slot, MechaChallenge2, 0xF0, 0x07) == 0) {
687 goto Error2_end;
688 }
689
690 _printf("card auth 0x07\n");
691
692 if (card_auth(port, slot, 0xF0, 0x08) == 0) {
693 goto Error2_end;
694 }
695
696 _printf("card auth 0x08\n");
697
698 if (card_auth2(port, slot, 0xF0, 0x09) == 0) {
699 goto Error2_end;
700 }
701
702 _printf("card auth 0x09\n");
703
704 if (card_auth(port, slot, 0xF0, 0x0A) == 0) {
705 goto Error2_end;
706 }
707
708 _printf("card auth 0x0a\n");
709
710 if (card_auth_write(port, slot, MechaChallenge1, 0xF0, 0x0B) == 0) {
711 goto Error2_end;
712 }
713
714 _printf("card auth 0x0b\n");
715
716 if (card_auth(port, slot, 0xF0, 0x0C) == 0) {
717 goto Error2_end;
718 }
719
720 _printf("card auth 0x0c\n");
721
722 if (card_auth2(port, slot, 0xF0, 0x0D) == 0) {
723 goto Error2_end;
724 }
725
726 _printf("card auth 0x0d\n");
727
728 if (card_auth(port, slot, 0xF0, 0x0E) == 0) {
729 goto Error2_end;
730 }
731
732 _printf("card auth 0x0e\n");
733
734 if (card_auth_read(port, slot, CardResponse1, 0xF0, 0x0F) == 0) { // Originally, it used the same region as CardNonce. But that might have just been a result of compiler code optimization.
735 goto Error2_end;
736 }
737
738 _printf("card auth 0x0f\n");
739
740 if (card_auth(port, slot, 0xF0, 0x10) == 0) {
741 goto Error2_end;
742 }
743
744 _printf("card auth 0x10\n");
745
746 if (card_auth_read(port, slot, CardResponse2, 0xF0, 0x11) == 0) {
747 goto Error2_end;
748 }
749
750 _printf("card auth 0x11\n");
751
752 if (mechacon_auth_86(CardResponse1, CardResponse2) == 0) {
753 goto Error2_end;
754 }
755
756 _printf("mechacon auth 0x86\n");
757
758 if (card_auth(port, slot, 0xF0, 0x12) == 0) {
759 goto Error2_end;
760 }
761
762 _printf("card auth 0x12\n");
763
764 if (card_auth_read(port, slot, CardResponse3, 0xF0, 0x13) == 0) {
765 goto Error2_end;
766 }
767
768 _printf("card auth 0x13\n");
769
770 if (mechacon_auth_87(CardResponse3) == 0) {
771 goto Error2_end;
772 }
773
774 _printf("mechacon auth 0x87\n");
775
776 if (pol_cal_cmplt() == 0) {
777 goto Error2_end;
778 }
779
780 _printf("mechacon auth 0x8f\n");
781
782 if (card_auth(port, slot, 0xF0, 0x14) == 0) {
783 goto Error2_end;
784 }
785
786 _printf("card auth 0x14\n");
787
788 if (mechacon_auth_88() == 0) {
789 goto Error2_end;
790 }
791
792 _printf("mechacon auth 0x88\n");
793
794 return 1;
795
796Error2_end:
797 card_auth_60(port, slot);
798 mechacon_auth_80(cnum);
799
800 return 0;
801}
802
803// 0x00000750 - export #07
804void SecrResetAuthCard(int port, int slot, int cnum)
805{
806 card_auth_60(port, slot);
807 mechacon_auth_80(cnum);
808}
809
810// 0x00002a98
811static unsigned short int GetHeaderLength(const void *buffer)
812{
813 return ((const SecrKELFHeader_t *)buffer)->KELF_header_size;
814}
815
816// 0x000009ac
817static int secr_set_header(int mode, int cnum, int arg2, void *buffer)
818{
819 unsigned short int HeaderLength;
820
821 HeaderLength = GetHeaderLength(buffer);
822 _printf("header length %d\n", HeaderLength);
823 if (write_HD_start(mode, cnum, arg2, HeaderLength) == 0) {
824 _printf("secr_set_header: fail write_HD_start\n");
825 return 0;
826 }
827
828 while (HeaderLength > 0) {
829 int write_data_result;
830
831 if (HeaderLength >= 0x10) { // if(HeaderLength>>4!=0)
832 write_data_result = write_data(buffer, 0x10);
833 buffer = (void *)((u8 *)buffer + 0x10);
834 HeaderLength -= 0x10;
835 } else {
836 write_data_result = write_data(buffer, HeaderLength);
837 HeaderLength = 0;
838 }
839
840 if (write_data_result == 0) {
841 _printf("secr_set_header: fail write_data\n");
842 return 0;
843 }
844 }
845
846 if (pol_cal_cmplt() == 0) {
847 _printf("secr_set_header: fail pol_cal_cmplt\n");
848 return 0;
849 }
850
851 return 1;
852}
853
854// 0x00000acc
855static int Read_BIT(SecrBitTable_t *BitTable)
856{
857 unsigned short int BitLength;
858 unsigned short int DataToCopy;
859
860 if (get_BIT_length(&BitLength) == 0) {
861 return 0;
862 }
863
864 DataToCopy = BitLength;
865
866 while (DataToCopy != 0) {
867 if (DataToCopy >= 0x10) {
868 if (func_00001b00(BitTable, 0x10) == 0) {
869 return 0;
870 }
871 BitTable = (SecrBitTable_t *)((u8 *)BitTable + 0x10);
872 DataToCopy -= 0x10;
873 } else {
874 if (func_00001b00(BitTable, DataToCopy) == 0) {
875 return 0;
876 }
877 DataToCopy = 0;
878 }
879 }
880
881 return BitLength;
882}
883
884// 0x00000ee0 - export #14
885int SecrDownloadHeader(int port, int slot, void *buffer, SecrBitTable_t *BitTable, s32 *pSize)
886{
887 int cnum;
888 int size;
889
890 if (GetMcCommandHandler() == NULL) {
891 _printf("mcCommand isn't assigned\n");
892 return 0;
893 }
894
895 if ((cnum = McDeviceIDToCNum(port, slot)) < 0) {
896 _printf("invalid cnum '%d'\n", cnum);
897 return 0;
898 }
899 if (secr_set_header(2, cnum, 0, buffer) == 0) {
900 return 0;
901 }
902
903 if ((size = Read_BIT(BitTable)) == 0) {
904 return 0;
905 }
906
907 if (pSize != NULL) {
908 *pSize = size;
909 }
910
911 return 1;
912}
913
914// 0x00002aa4
915static unsigned int get_BitTableOffset(const void *buffer)
916{
917 const SecrKELFHeader_t *header = buffer;
918 int offset = sizeof(SecrKELFHeader_t);
919
920 if (header->BIT_count > 0)
921 offset += header->BIT_count * sizeof(SecrBitBlockData_t); // They used a loop for this. D:
922 if ((header->flags & 1) != 0)
923 offset += ((const unsigned char *)buffer)[offset] + 1;
924 if ((header->flags & 0xF000) == 0)
925 offset += 8;
926 return (offset + 0x20); // Goes after Kbit and Kc.
927}
928
929// 0x00000b5c
930static int func_00000b5c(const void *block, unsigned int size)
931{
932 if (mechacon_set_block_size(size) == 0) {
933 return 0;
934 }
935
936 while (size > 0) {
937 if (write_data(block, 0x10) == 0) {
938 return 0;
939 }
940 block = (const void *)((const u8 *)block + 0x10);
941 size -= 0x10;
942 }
943
944 if (pol_cal_cmplt() == 0) {
945 return 0;
946 }
947
948 return 1;
949}
950
951// 0x00000fb4 - export #15
952int SecrDownloadBlock(void *block, unsigned int size)
953{
954 if (func_00000b5c(block, size) != 1) {
955 return 0;
956 }
957
958 return 1;
959}
960
961// 0x00000c94
962static int scePreEncryptKbit(void *kbit)
963{
964 if (_PreEncryptKbit1(kbit) == 0) {
965 return 0;
966 }
967
968 if (_PreEncryptKbit2((void *)((u8 *)kbit + 8)) != 1) {
969 return 0;
970 }
971
972 return 1;
973}
974
975
976// 0x00000cd4
977static int scePreEncryptKc(void *kc)
978{
979 if (_PreEncryptKc1(kc) == 0) {
980 return 0;
981 }
982
983 if (_PreEncryptKc2((void *)((u8 *)kc + 8)) != 1) {
984 return 0;
985 }
986
987 return 1;
988}
989
990// 0x00000894
991static int card_encrypt(int port, int slot, void *buffer)
992{
993 if (GetMcCommandHandler() == NULL) {
994 return 0;
995 }
996
997 _printf("card encrypt start\n");
998
999 if (card_auth(port, slot, 0xF2, 0x50) == 0) {
1000 return 0;
1001 }
1002
1003 _printf("card encrypt 0x50\n");
1004
1005 if (card_auth_write(port, slot, buffer, 0xF2, 0x51) == 0) {
1006 return 0;
1007 }
1008
1009 _printf("card encrypt 0x51\n");
1010
1011 if (card_auth(port, slot, 0xF2, 0x52) == 0) {
1012 return 0;
1013 }
1014
1015 _printf("card encrypt 0x52\n");
1016
1017 if (card_auth_read(port, slot, buffer, 0xF2, 0x53) == 0) {
1018 return 0;
1019 }
1020
1021 _printf("card encrypt 0x53\n");
1022
1023 return 1;
1024}
1025
1026// 0x00000fd4 - export #17
1027int SecrDownloadGetKbit(int port, int slot, void *kbit)
1028{
1029 if (scePreEncryptKbit(kbit) == 0) {
1030 return 0;
1031 }
1032
1033 if (card_encrypt(port, slot, kbit) == 0) {
1034 return 0;
1035 }
1036
1037 if (card_encrypt(port, slot, (void *)((u8 *)kbit + 8)) == 0) {
1038 return 0;
1039 }
1040
1041 return 1;
1042}
1043
1044// 0x00001048 - export #18
1045int SecrDownloadGetKc(int port, int slot, void *kc)
1046{
1047 if (scePreEncryptKc(kc) == 0) {
1048 return 0;
1049 }
1050
1051 if (card_encrypt(port, slot, kc) == 0) {
1052 return 0;
1053 }
1054
1055 if (card_encrypt(port, slot, (void *)((u8 *)kc + 8)) == 0) {
1056 return 0;
1057 }
1058
1059 return 1;
1060}
1061
1062// 0x00000d14
1063static int func_00000d14(void *icvps2)
1064{
1065 if (func_00001ed8(icvps2) == 0) {
1066 return 0;
1067 }
1068
1069 return 1;
1070}
1071
1072// 0x000010bc - export #19
1073int SecrDownloadGetICVPS2(void *icvps2)
1074{
1075 if (func_00000d14(icvps2) == 0) {
1076 return 0;
1077 }
1078
1079 return 1;
1080}
1081
1082// 0x00002b0c
1083static int Uses_ICVPS2(const void *buffer)
1084{
1085 return (((const SecrKELFHeader_t *)buffer)->flags >> 1 & 1);
1086}
1087
1088// 0x000012c0 - export #16
1089void *SecrDownloadFile(int port, int slot, void *buffer)
1090{
1091 SecrBitTable_t BitTableData;
1092 unsigned char kbit[16], kcontent[16];
1093 unsigned int offset, i;
1094
1095 _printf("SecrDownloadFile start\n");
1096 get_BitTableOffset(buffer); // Doesn't use its return value?
1097 if (SecrDownloadHeader(port, slot, buffer, &BitTableData, NULL) == 0) {
1098 _printf("SecrDownloadFile: Cannot encrypt header\n");
1099 return NULL;
1100 }
1101
1102 offset = BitTableData.header.headersize;
1103 for (i = 0; i < BitTableData.header.block_count; i++) {
1104 if (BitTableData.blocks[i].flags & 2) {
1105 if (!SecrDownloadBlock((void *)((u8 *)buffer + offset), BitTableData.blocks[i].size)) {
1106 _printf("SecrDownloadFile: failed\n");
1107 return NULL;
1108 }
1109 }
1110 offset += BitTableData.blocks[i].size;
1111 }
1112
1113 if (SecrDownloadGetKbit(port, slot, kbit) == 0) {
1114 _printf("SecrDownloadFile: Cannot get kbit\n");
1115 return NULL;
1116 }
1117 if (SecrDownloadGetKc(port, slot, kcontent) == 0) {
1118 _printf("SecrDownloadFile: Cannot get kc\n");
1119 return NULL;
1120 }
1121
1122 store_kbit(buffer, kbit);
1123 store_kc(buffer, kcontent);
1124
1125 if (Uses_ICVPS2(buffer) == 1) {
1126 unsigned char icvps2[8];
1127
1128 if (SecrDownloadGetICVPS2(icvps2) == 0) {
1129 _printf("SecrDownloadFile: Cannot get icvps2\n");
1130 return NULL;
1131 }
1132
1133 store_icvps2(buffer, icvps2);
1134 }
1135
1136 _printf("SecrDownloadFile complete\n");
1137
1138 return buffer;
1139}
1140
1141#ifdef BUILDING_ARCADE_SECRMAN
1142// Authentication routine for COH-H10020 security dongles
1143// Only useful for namco system 246/256
1144int SecrAuthDongle(int port, int slot, int cnum)
1145{
1146 unsigned char
1147 MechaChallenge2[8],
1148 CardIV[8],
1149 CardMaterial[8],
1150 CardNonce[8],
1151 MechaChallenge1[8],
1152 MechaChallenge3[8],
1153 CardResponse1[8],
1154 CardResponse2[8],
1155 CardResponse3[8];
1156
1157 if (GetMcCommandHandler() == NULL) {
1158 _printf("mcCommand isn't assigned\n");
1159 return 0;
1160 }
1161
1162 _printf("SecrAuthDongle start\n");
1163
1164 memset(MechaChallenge1, 0, sizeof(MechaChallenge1));
1165
1166 if (card_auth_60(port, slot) == 0) {
1167 return 0;
1168 }
1169
1170 _printf("dongle auth 0x60\n");
1171
1172 if (mechacon_auth_80(cnum) == 0) {
1173 return 0;
1174 }
1175
1176 _printf("mechacon auth 0x80\n");
1177
1178 /* El_isra:
1179 * SecrAuthDongle does not perform the card_auth_key_change that should be here
1180 * Is this what makes COH-H models only accept one dongle per boot session?
1181 */
1182
1183 if (card_auth(port, slot, 0xF0, 0x00) == 0) {
1184 card_auth_60(port, slot);
1185 return 0;
1186 }
1187
1188 _printf("dongle auth 0x00\n");
1189
1190 if (mechacon_auth_81(cnum | 0x40) == 0) { // SecrAuthCard passes the cnum as-is, no xoring.
1191 card_auth_60(port, slot);
1192 return 0;
1193 }
1194
1195 _printf("mechacon auth 0x81\n");
1196
1197 if (card_auth_read(port, slot, CardIV, 0xF0, 0x01) == 0) {
1198 goto Error2_end;
1199 }
1200
1201 _printf("dongle auth 0x01\n");
1202
1203 if (card_auth_read(port, slot, CardMaterial, 0xF0, 0x02) == 0) {
1204 goto Error2_end;
1205 }
1206
1207 _printf("dongle auth 0x02\n");
1208
1209 if (mechacon_auth_82(CardIV, CardMaterial) == 0) {
1210 goto Error2_end;
1211 }
1212
1213 _printf("mechacon auth 0x82\n");
1214
1215 if (card_auth(port, slot, 0xF0, 0x03) == 0) {
1216 goto Error2_end;
1217 }
1218
1219 _printf("dongle auth 0x03\n");
1220
1221 if (card_auth_read(port, slot, CardNonce, 0xF0, 0x04) == 0) {
1222 goto Error2_end;
1223 }
1224
1225 _printf("dongle auth 0x04\n");
1226
1227 if (mechacon_auth_83(CardNonce) == 0) {
1228 goto Error2_end;
1229 }
1230
1231 _printf("mechacon auth 0x83\n");
1232
1233 if (card_auth(port, slot, 0xF0, 0x05) == 0) {
1234 goto Error2_end;
1235 }
1236
1237 _printf("dongle auth 0x05\n");
1238
1239 if (pol_cal_cmplt() == 0) {
1240 goto Error2_end;
1241 }
1242
1243 _printf("mechacon auth 0x8f\n");
1244
1245 if (mechacon_auth_84(MechaChallenge1, MechaChallenge2) == 0) {
1246 goto Error2_end;
1247 }
1248
1249 _printf("mechacon auth 0x84\n");
1250
1251 if (mechacon_auth_85(&MechaChallenge2[4], MechaChallenge3) == 0) {
1252 goto Error2_end;
1253 }
1254
1255 _printf("mechacon auth 0x85\n");
1256
1257 if (card_auth_write(port, slot, MechaChallenge3, 0xF0, 0x06) == 0) {
1258 goto Error2_end;
1259 }
1260
1261 _printf("dongle auth 0x06\n");
1262
1263 if (card_auth_write(port, slot, MechaChallenge2, 0xF0, 0x07) == 0) {
1264 goto Error2_end;
1265 }
1266
1267 _printf("dongle auth 0x07\n");
1268
1269 if (card_auth(port, slot, 0xF0, 0x08) == 0) {
1270 goto Error2_end;
1271 }
1272
1273 _printf("dongle auth 0x08\n");
1274
1275 if (card_auth2(port, slot, 0xF0, 0x09) == 0) {
1276 goto Error2_end;
1277 }
1278
1279 _printf("dongle auth 0x09\n");
1280
1281 if (card_auth(port, slot, 0xF0, 0x0A) == 0) {
1282 goto Error2_end;
1283 }
1284
1285 _printf("dongle auth 0x0a\n");
1286
1287 if (card_auth_write(port, slot, MechaChallenge1, 0xF0, 0x0B) == 0) {
1288 goto Error2_end;
1289 }
1290
1291 _printf("dongle auth 0x0b\n");
1292
1293 if (card_auth(port, slot, 0xF0, 0x0C) == 0) {//
1294 goto Error2_end;
1295 }
1296
1297 _printf("dongle auth 0x0c\n");
1298
1299 if (card_auth2(port, slot, 0xF0, 0x0D) == 0) {//
1300 goto Error2_end;
1301 }
1302
1303 _printf("dongle auth 0x0d\n");
1304
1305 if (card_auth(port, slot, 0xF0, 0x0E) == 0) {//
1306 goto Error2_end;
1307 }
1308
1309 _printf("dongle auth 0x0e\n");
1310 //sp193 comment on SecrAuthCard for the following function call: Originally, it used the same region as CardNonce. But that might have just been a result of compiler code optimization.
1311 //El_isra: contrary to what sp193 comments about this, ghidra shows this as a separate buffer than CardNonce. on both SecrAuthCard and SecrAuthDongle. maybe error, or an actual diff on the SECRMAN version sp193 reversed? who knows...
1312 if (card_auth_read(port, slot, CardResponse1, 0xF0, 0x0F) == 0) {
1313 goto Error2_end;
1314 }
1315
1316 _printf("dongle auth 0x0f\n");
1317
1318 if (card_auth(port, slot, 0xF0, 0x10) == 0) {
1319 goto Error2_end;
1320 }
1321
1322 _printf("dongle auth 0x10\n");
1323
1324 if (card_auth_read(port, slot, CardResponse2, 0xF0, 0x11) == 0) {
1325 goto Error2_end;
1326 }
1327
1328 _printf("dongle auth 0x11\n");
1329
1330 if (mechacon_auth_86(CardResponse1, CardResponse2) == 0) {
1331 goto Error2_end;
1332 }
1333
1334 _printf("mechacon auth 0x86\n");
1335
1336 if (card_auth(port, slot, 0xF0, 0x12) == 0) {
1337 goto Error2_end;
1338 }
1339
1340 _printf("dongle auth 0x12\n");
1341
1342 if (card_auth_read(port, slot, CardResponse3, 0xF0, 0x13) == 0) {
1343 goto Error2_end;
1344 }
1345
1346 _printf("dongle auth 0x13\n");
1347
1348 if (mechacon_auth_87(CardResponse3) == 0) {
1349 goto Error2_end;
1350 }
1351
1352 _printf("mechacon auth 0x87\n");
1353
1354 if (pol_cal_cmplt() == 0) {
1355 goto Error2_end;
1356 }
1357
1358 _printf("mechacon auth 0x8f\n");
1359
1360 if (card_auth(port, slot, 0xF0, 0x14) == 0) {//
1361 goto Error2_end;
1362 }
1363
1364 _printf("card auth 0x14\n");
1365
1366 if (mechacon_auth_88() == 0) {
1367 goto Error2_end;
1368 }
1369
1370 _printf("mechacon auth 0x88!\n");
1371
1372 return 1;
1373
1374Error2_end:
1375 card_auth_60(port, slot);
1376 mechacon_auth_80(cnum);
1377
1378 return 0;
1379}
1380#endif
struct KELF_Header SecrKELFHeader_t
SecrBitBlockData_t blocks[63]
struct SecrBitBlockData SecrBitBlockData_t