void cps2_decrypt(const u32 *master_key) { u16 *rom = (u16 *)memory_region_cpu1; int length = memory_length_cpu1; u16 *dec = (u16 *)memory_region_user1; int upper_limit = memory_length_user1; int i; u32 key1[4]; // expand master key to 1st FN 96-bit key expand_1st_key(key1, master_key); // add extra bits for s-boxes with less than 6 inputs key1[0] ^= BIT(key1[0], 1) << 4; key1[0] ^= BIT(key1[0], 2) << 5; key1[0] ^= BIT(key1[0], 8) << 11; key1[1] ^= BIT(key1[1], 0) << 5; key1[1] ^= BIT(key1[1], 8) << 11; key1[2] ^= BIT(key1[2], 1) << 5; key1[2] ^= BIT(key1[2], 8) << 11; for (i = 0; i < 0x10000; ++i) { int a; u16 seed; u32 subkey[2]; u32 key2[4]; if ((i & 0x1fff) == 0) { msg_printf("Decrypting... %d%%\n", i*100/0x10000); } // pass the address through FN1 seed = feistel(i, fn1_groupA, fn1_groupB, fn1_r1_boxes, fn1_r2_boxes, fn1_r3_boxes, fn1_r4_boxes, key1[0], key1[1], key1[2], key1[3]); // expand the result to 64-bit expand_subkey(subkey, seed); // XOR with the master key subkey[0] ^= master_key[0]; subkey[1] ^= master_key[1]; // expand key to 2nd FN 96-bit key expand_2nd_key(key2, subkey); // add extra bits for s-boxes with less than 6 inputs key2[0] ^= BIT(key2[0], 0) << 5; key2[0] ^= BIT(key2[0], 6) << 11; key2[1] ^= BIT(key2[1], 0) << 5; key2[1] ^= BIT(key2[1], 1) << 4; key2[2] ^= BIT(key2[2], 2) << 5; key2[2] ^= BIT(key2[2], 3) << 4; key2[2] ^= BIT(key2[2], 7) << 11; key2[3] ^= BIT(key2[3], 1) << 5; // decrypt the opcodes for (a = i; a < length/2 && a < upper_limit/2; a += 0x10000) { dec[a] = feistel(rom[a], fn2_groupA, fn2_groupB, fn2_r1_boxes, fn2_r2_boxes, fn2_r3_boxes, fn2_r4_boxes, key2[0], key2[1], key2[2], key2[3]); } // copy the unencrypted part (not really needed) /* while (a < length/2) { dec[a] = rom[a]; a += 0x10000; } */ } msg_printf("Decrypting... Complete\n"); //m68000_set_encrypted_range(0x000000, length - 1, dec); }
int main (int argc, char *argv[]) { int i = 0; char c; unsigned long data = 4037734570; unsigned long subkey[2] = {453177088, 4235227648}; char input[] = "11110000101010101111000010101010"; char output[] = "00100011010010101010100110111011"; char subkey_string[] = "000110110000001011101111111111000111000001110010"; printf("\x1b[1;35mtestfeistel\x1b[0m\n\n"); printf("Bits before feistel:\t "); for (i = 0; i < 32; i++) { if (bitmasks[i + 1] & data) { printf("1"); } else { printf("0"); } if (((i + 1) % 4) == 0) { printf(" "); } } printf("\nBits should be:\t\t "); for (i = 0; i < 32; i++) { printf("%c", input[i]); if (((i + 1) % 4) == 0) { printf(" "); } } printf("\n"); printf("Subkey: \t\t"); for (i = 0; i < 48; i++) { printf("%c", subkey_string[i]); if (((i + 1) % 6) == 0) { printf(" "); } } printf("\n"); data = feistel(&data, (unsigned long *)subkey); printf("After feistel:\t\t "); for (i = 0; i < 32; i++) { if (bitmasks[i + 1] & data) { printf("1"); } else { printf("0"); } if (((i + 1) % 4) == 0) { printf(" "); } } printf("\n"); printf("Should be: \t\t "); for (i = 0; i < 32; i++) { printf("%c", output[i]); if (((i + 1) % 4) == 0) { printf(" "); } if (bitmasks[i + 1] & data) { c = '1'; } else { c = '0'; } if (c != output[i]) { printf("\n\x1b[1;31mFAILED!\x1b[0m\n"); goto QUIT; } } printf("\n"); printf("\n\x1b[1;35m\\testfeistel\x1b[0m\n"); printf("\n\x1b[1;34mPASSED!\x1b[0m\n\n"); QUIT: return 0; }
static void cps2_decrypt(const UINT32 *master_key, unsigned int upper_limit) { UINT16 *rom = (UINT16 *)memory_region(REGION_CPU1); int length = memory_region_length(REGION_CPU1); UINT16 *dec = auto_malloc(length); int i; UINT32 key1[4]; // expand master key to 1st FN 96-bit key expand_1st_key(key1, master_key); // add extra bits for s-boxes with less than 6 inputs key1[0] ^= BIT(key1[0], 1) << 4; key1[0] ^= BIT(key1[0], 2) << 5; key1[0] ^= BIT(key1[0], 8) << 11; key1[1] ^= BIT(key1[1], 0) << 5; key1[1] ^= BIT(key1[1], 8) << 11; key1[2] ^= BIT(key1[2], 1) << 5; key1[2] ^= BIT(key1[2], 8) << 11; for (i = 0; i < 0x10000; ++i) { int a; UINT16 seed; UINT32 subkey[2]; UINT32 key2[4]; if ((i & 0xff) == 0) { char loadingMessage[256]; // for displaying with UI sprintf(loadingMessage, "Decrypting %d%%", i*100/0x10000); ui_set_startup_text(loadingMessage,FALSE); } // pass the address through FN1 seed = feistel(i, fn1_groupA, fn1_groupB, fn1_r1_boxes, fn1_r2_boxes, fn1_r3_boxes, fn1_r4_boxes, key1[0], key1[1], key1[2], key1[3]); // expand the result to 64-bit expand_subkey(subkey, seed); // XOR with the master key subkey[0] ^= master_key[0]; subkey[1] ^= master_key[1]; // expand key to 2nd FN 96-bit key expand_2nd_key(key2, subkey); // add extra bits for s-boxes with less than 6 inputs key2[0] ^= BIT(key2[0], 0) << 5; key2[0] ^= BIT(key2[0], 6) << 11; key2[1] ^= BIT(key2[1], 0) << 5; key2[1] ^= BIT(key2[1], 1) << 4; key2[2] ^= BIT(key2[2], 2) << 5; key2[2] ^= BIT(key2[2], 3) << 4; key2[2] ^= BIT(key2[2], 7) << 11; key2[3] ^= BIT(key2[3], 1) << 5; // decrypt the opcodes for (a = i; a < length/2 && a < upper_limit/2; a += 0x10000) { dec[a] = feistel(rom[a], fn2_groupA, fn2_groupB, fn2_r1_boxes, fn2_r2_boxes, fn2_r3_boxes, fn2_r4_boxes, key2[0], key2[1], key2[2], key2[3]); } // copy the unencrypted part (not really needed) while (a < length/2) { dec[a] = rom[a]; a += 0x10000; } } memory_set_decrypted_region(0, 0x000000, length - 1, dec); m68k_set_encrypted_opcode_range(0,0,length); #if 0 { FILE *f; f = fopen("d:/s.rom","wb"); fwrite(rom,1,0x100000,f); fclose(f); f = fopen("d:/s.dec","wb"); fwrite(dec,1,0x100000,f); fclose(f); } #endif }