PS2SDK
PS2 Homebrew Libraries
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 
26 IRX_ID(MODNAME, 1, 4);
27 
28 #ifdef DEX_SUPPORT
29 int IsDEX;
30 #endif
31 
32 extern struct irx_export_table _exp_secrman;
33 
34 #if 0
35 static void _printf(const char *format, ...);
36 #endif
37 
39 {
40  SecrBitTableHeader_t header;
41  SecrBitBlockData_t *blocks;
42  unsigned int padding; // Doesn't seem to be used.
43 };
44 
45 static loadfile_elf_load_proc_callback_t loadfile_elf_load_proc; // 0x00003d20
46 static loadfile_check_valid_ee_elf_callback_t loadfile_check_valid_ee_elf; // 0x00003d24
47 static loadfile_elf_get_program_header_callback_t loadfile_elf_get_program_header; // 0x00003d28
48 static loadfile_elf_load_alloc_buffer_from_heap_callback_t loadfile_elf_load_alloc_buffer_from_heap; // 0x00003d2c
49 static loadfile_elf_load_dealloc_buffer_from_heap_callback_t loadfile_elf_load_dealloc_buffer_from_heap; // 0x00003d30
50 
51 // Function prototypes.
52 static int card_decrypt(int port, int slot, void *buffer);
53 static int func_00000bfc(void *dest, unsigned int size);
54 static int func_00002eb0(struct ModloadBitTableDescriptor *ModloadBitTableDescriptor, int fd, int port, int slot, int device);
55 static 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));
56 static int secrman_loadfile_read_callback_card(int fd, loadfile_allocate_handler_struct_t *allocate_info, void *read_callback_userdata);
57 static 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);
58 static 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);
59 static int secrman_loadfile_read_callback_disk(int fd, loadfile_allocate_handler_struct_t *allocate_info, void *read_callback_userdata);
60 static 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);
61 static void SecrGetLoadfileCallbacks(SetLoadfileCallbacks_struct_t *unknown);
62 static void RegisterSecrCallbackHandlers(void);
63 static int card_encrypt(int port, int slot, void *buffer);
64 static unsigned short int GetHeaderLength(const void *buffer);
65 static int secr_set_header(int mode, int cnum, int arg2, void *buffer);
66 static int Read_BIT(SecrBitTable_t *BitTable);
67 static unsigned int get_BitTableOffset(const void *buffer);
68 static int func_00000b5c(const void *block, unsigned int size);
69 
71 static int scePreEncryptKbit(void *kbit);
72 
74 static int scePreEncryptKc(void *kc);
75 static int func_00000d14(void *icvps2);
76 static int Uses_ICVPS2(const void *buffer);
77 
78 // 0x00000000
79 #if 0
80 static void _printf(const char *format, ...){
81 
82 }
83 #endif
84 
85 // 0x0000077c
86 static 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
122 int 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
179 static 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
213 int 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
227 void *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
253 int 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
275 int 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
288 void *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
314 static 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. */
368 static 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
431 static 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
437 static 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
476 static 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
482 static 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
488 static 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
494 static 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
507 static void RegisterSecrCallbackHandlers(void)
508 {
509  SetSecrmanCallbacks(&SecrCardBootFile, &SecrDiskBootFile, &SecrGetLoadfileCallbacks);
510 }
511 
512 // 0x00000018
513 int _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
543 int _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
552 void SecrSetMcCommandHandler(McCommandHandler_t handler)
553 {
554  SetMcCommandHandler(handler);
555 }
556 
557 // 0x00000084 - export #05
558 void 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.
565 int 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 
796 Error2_end:
797  card_auth_60(port, slot);
798  mechacon_auth_80(cnum);
799 
800  return 0;
801 }
802 
803 // 0x00000750 - export #07
804 void SecrResetAuthCard(int port, int slot, int cnum)
805 {
806  card_auth_60(port, slot);
807  mechacon_auth_80(cnum);
808 }
809 
810 // 0x00002a98
811 static unsigned short int GetHeaderLength(const void *buffer)
812 {
813  return ((const SecrKELFHeader_t *)buffer)->KELF_header_size;
814 }
815 
816 // 0x000009ac
817 static 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
855 static 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
885 int 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
915 static 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
930 static 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
952 int 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
962 static 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
977 static 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
991 static 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
1027 int 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
1045 int 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
1063 static 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
1073 int SecrDownloadGetICVPS2(void *icvps2)
1074 {
1075  if (func_00000d14(icvps2) == 0) {
1076  return 0;
1077  }
1078 
1079  return 1;
1080 }
1081 
1082 // 0x00002b0c
1083 static int Uses_ICVPS2(const void *buffer)
1084 {
1085  return (((const SecrKELFHeader_t *)buffer)->flags >> 1 & 1);
1086 }
1087 
1088 // 0x000012c0 - export #16
1089 void *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
1144 int 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 
1374 Error2_end:
1375  card_auth_60(port, slot);
1376  mechacon_auth_80(cnum);
1377 
1378  return 0;
1379 }
1380 #endif
SecrBitBlockData_t
struct SecrBitBlockData SecrBitBlockData_t
SecrBitTableHeader::block_count
u8 block_count
Definition: libsecr-common.h:36
SecrBitBlockData
Definition: libsecr-common.h:22
loadfile_allocate_handler_struct_
Definition: modload.h:90
sysclib.h
SecrKELFHeader_t
struct KELF_Header SecrKELFHeader_t
loadcore.h
sio2man.h
SecrBitBlockData::flags
u32 flags
Definition: libsecr-common.h:27
SecrBitTableHeader::headersize
u32 headersize
Definition: libsecr-common.h:34
irx.h
loadfile_file_load_handler_struct_
Definition: modload.h:70
ModloadBitTableDescriptor
Definition: secrman.c:38
KELF_Header::BIT_count
u16 BIT_count
Definition: libsecr-common.h:62
SecrBitTable
Definition: libsecr-common.h:43
irx_export_table
Definition: irx.h:90
stdio.h
SecrBitBlockData::size
u32 size
Definition: libsecr-common.h:25
SecrBitTableHeader
Definition: libsecr-common.h:31
SecrBitTable::blocks
SecrBitBlockData_t blocks[63]
Definition: libsecr-common.h:47
ioman.h
loadfile_ee_elf_ringbuffer_content_
Definition: modload.h:82
SetLoadfileCallbacks_struct_
Definition: modload.h:108
KELF_Header
Definition: libsecr-common.h:51
modload.h
secrman.h
KELF_Header::flags
u16 flags
Definition: libsecr-common.h:60