1 // license:BSD-3-Clause
2 // copyright-holders:Nicola Salmoria
3 /***************************************************************************
4 
5 "Kabuki" Z80 encryption
6 
7 
8 The "Kabuki" is a custom Z80 module which runs encrypted code. The encryption
9 key is stored in some battery-backed RAM, therefore the chip has the annoying
10 habit of stopping working every few years, when the battery dies.
11 
12 The suicide battery supplies power to pin 28. When you remove the battery, if
13 you pull pin 28 low, the Kabuki will behave like a normal Z80.
14 
15 
16 Check at the bottom of this text to see a list of all the known games which
17 use this chip.
18 
19 
20 How it works:
21 The base operation is a bit swap which affects couples of adjacent bits.
22 Each of the 4 couples may or may not be swapped, depending on the address of
23 the byte and on whether it is an opcode or data.
24 The decryption consists of these steps:
25 - bitswap
26 - ROL
27 - bitswap
28 - XOR with a key
29 - ROL
30 - bitswap
31 - ROL
32 - bitswap
33 
34 To know how to apply the bit swap, take the address of the byte to decode and:
35 - if the byte is an opcode, add addr_key to the address
36 - if the byte is data, XOR the address with 1FC0, add 1, and then add addr_key
37 You'll get a 16-bit word. The first two bitswaps depend on bits 0-7 of that
38 word, while the second two on bits 8-15. When a bit in the word is 1, swap the
39 two bits, otherwise don't. The exact couple of bits affected depends on the
40 game and is identified in this file with two keys: swap_key1 and swap_key2
41 (which are just permutations of the numbers 0-7, not full 32-bit integers).
42 
43 
44 Key space size:
45 - swap_key1  8! = 40320
46 - swap_key2  8! = 40320
47 - addr_key   2^16 = 65536
48 - xor_key    2^8 = 256
49 - total      2.7274 * 10^16
50 
51 
52 Weaknesses:
53 - 0x00 and 0xff, having all the bits set to the same value, are not affected
54   by bit permutations after the XOR. Therefore, their encryption is the same
55   regardless of the high 8 bits of the address, and of the value of
56   swap_key2. If there is a long stream of 0x00 or 0xff in the original data,
57   this can be used to find by brute force all the candidates for swap_key1,
58   xor_key, and for the low 8 bits of addr_key. This is a serious weakness
59   which dramatically reduces the security of the encryption.
60 - A 0x00 is always encrypted as a byte with as many 1s as xor_key; a 0xff is
61   always encrypted as a byte with as many 0s as xor_key has 1s. So you just
62   need to know one 0x00 or 0xff in the unencrypted data to know how many 1s
63   there are in xor_key.
64 - Once you have restricted the range for swap_key1 and you know the number of
65   1s in the xor_key, you can easily use known plaintext attacks and brute
66   force to find the remaining keys. Long strings like THIS GAME IS FOR USE IN
67   and ABCDEFGHIJKLMNOPQRSTUVWXYZ can be found by comparing the number of 1s
68   in the clear and encrypted data, taking xor_key into account. When you have
69   found where the string is, use brute force to reduce the key space.
70 
71 
72 Known games:
73                                          swap_key1 swap_key2 addr_key xor_key
74 Mahjong Gakuen 2 Gakuen-chou no Fukushuu 76543210  01234567    aa55     a5
75 Poker Ladies                              "    "    "    "      ""      ""
76 Dokaben                                   "    "    "    "      ""      ""
77 Dokaben 2                                             unknown
78 Pang / Buster Bros / Pomping World       01234567  76543210    6548     24
79 Capcom Baseball                           "    "    "    "      ""      ""
80 Capcom World                             04152637  40516273    5751     43
81 Adventure Quiz 2 Hatena ? no Dai-Bouken  45670123  45670123    5751     43
82 Super Pang (World)                       45670123  45670123    5852     43
83 Super Pang (Japan)                       45123670  67012345    55aa     5a
84 Super Buster Bros                        45670123  45670123    2130     12
85 Super Marukin-Ban                        54321076  54321076    4854     4f
86 Quiz Tonosama no Yabou                   12345670  12345670    1111     11
87 Ashita Tenki ni Naare                                 unknown
88 Quiz Sangokushi                          23456701  23456701    1828     18
89 Block Block                              02461357  64207531    0002     01
90 
91 Warriors of Fate                         01234567  54163072    5151     51
92 Cadillacs and Dinosaurs                  76543210  24601357    4343     43
93 Punisher                                 67452103  75316024    2222     22
94 Slam Masters                             54321076  65432107    3131     19
95 
96 ***************************************************************************/
97 
98 #include "emu.h"
99 
100 
101 
bitswap1(int src,int key,int select)102 static int bitswap1(int src,int key,int select)
103 {
104 	if (select & (1 << ((key >> 0) & 7)))
105 		src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
106 	if (select & (1 << ((key >> 4) & 7)))
107 		src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
108 	if (select & (1 << ((key >> 8) & 7)))
109 		src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
110 	if (select & (1 << ((key >>12) & 7)))
111 		src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
112 
113 	return src;
114 }
115 
bitswap2(int src,int key,int select)116 static int bitswap2(int src,int key,int select)
117 {
118 	if (select & (1 << ((key >>12) & 7)))
119 		src = (src & 0xfc) | ((src & 0x01) << 1) | ((src & 0x02) >> 1);
120 	if (select & (1 << ((key >> 8) & 7)))
121 		src = (src & 0xf3) | ((src & 0x04) << 1) | ((src & 0x08) >> 1);
122 	if (select & (1 << ((key >> 4) & 7)))
123 		src = (src & 0xcf) | ((src & 0x10) << 1) | ((src & 0x20) >> 1);
124 	if (select & (1 << ((key >> 0) & 7)))
125 		src = (src & 0x3f) | ((src & 0x40) << 1) | ((src & 0x80) >> 1);
126 
127 	return src;
128 }
129 
bytedecode(int src,int swap_key1,int swap_key2,int xor_key,int select)130 static int bytedecode(int src,int swap_key1,int swap_key2,int xor_key,int select)
131 {
132 	src = bitswap1(src,swap_key1 & 0xffff,select & 0xff);
133 	src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
134 	src = bitswap2(src,swap_key1 >> 16,select & 0xff);
135 	src ^= xor_key;
136 	src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
137 	src = bitswap2(src,swap_key2 & 0xffff,select >> 8);
138 	src = ((src & 0x7f) << 1) | ((src & 0x80) >> 7);
139 	src = bitswap1(src,swap_key2 >> 16,select >> 8);
140 	return src;
141 }
142 
kabuki_decode(uint8_t * src,uint8_t * dest_op,uint8_t * dest_data,int base_addr,int length,int swap_key1,int swap_key2,int addr_key,int xor_key)143 static void kabuki_decode(uint8_t *src,uint8_t *dest_op,uint8_t *dest_data,
144 		int base_addr,int length,int swap_key1,int swap_key2,int addr_key,int xor_key)
145 {
146 	int A;
147 	int select;
148 
149 	for (A = 0;A < length;A++)
150 	{
151 		/* decode opcodes */
152 		select = (A + base_addr) + addr_key;
153 		dest_op[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
154 
155 		/* decode data */
156 		select = ((A + base_addr) ^ 0x1fc0) + addr_key + 1;
157 		dest_data[A] = bytedecode(src[A],swap_key1,swap_key2,xor_key,select);
158 	}
159 }
160 
161 
162 
mitchell_decode(uint8_t * src,uint8_t * dst,int size,int swap_key1,int swap_key2,int addr_key,int xor_key)163 static void mitchell_decode(uint8_t *src, uint8_t *dst, int size, int swap_key1,int swap_key2,int addr_key,int xor_key)
164 {
165 	int numbanks = (size - 0x10000) / 0x4000;
166 
167 	kabuki_decode(src,dst,src,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key);
168 
169 	src += 0x10000;
170 	dst += 0x10000;
171 	for (int i = 0; i < numbanks; i++)
172 		kabuki_decode(src+i*0x4000,dst+i*0x4000,src+i*0x4000,0x8000,0x4000, swap_key1,swap_key2,addr_key,xor_key);
173 }
174 
mgakuen2_decode(uint8_t * src,uint8_t * dst,int size)175 void mgakuen2_decode(uint8_t *src, uint8_t *dst, int size) { mitchell_decode(src,dst,size,0x76543210,0x01234567,0xaa55,0xa5); }
pang_decode(uint8_t * src,uint8_t * dst,int size)176 void pang_decode(uint8_t *src, uint8_t *dst, int size)     { mitchell_decode(src,dst,size,0x01234567,0x76543210,0x6548,0x24); }
cworld_decode(uint8_t * src,uint8_t * dst,int size)177 void cworld_decode(uint8_t *src, uint8_t *dst, int size)   { mitchell_decode(src,dst,size,0x04152637,0x40516273,0x5751,0x43); }
hatena_decode(uint8_t * src,uint8_t * dst,int size)178 void hatena_decode(uint8_t *src, uint8_t *dst, int size)   { mitchell_decode(src,dst,size,0x45670123,0x45670123,0x5751,0x43); }
spang_decode(uint8_t * src,uint8_t * dst,int size)179 void spang_decode(uint8_t *src, uint8_t *dst, int size)    { mitchell_decode(src,dst,size,0x45670123,0x45670123,0x5852,0x43); }
spangj_decode(uint8_t * src,uint8_t * dst,int size)180 void spangj_decode(uint8_t *src, uint8_t *dst, int size)   { mitchell_decode(src,dst,size,0x45123670,0x67012345,0x55aa,0x5a); }
sbbros_decode(uint8_t * src,uint8_t * dst,int size)181 void sbbros_decode(uint8_t *src, uint8_t *dst, int size)   { mitchell_decode(src,dst,size,0x45670123,0x45670123,0x2130,0x12); }
marukin_decode(uint8_t * src,uint8_t * dst,int size)182 void marukin_decode(uint8_t *src, uint8_t *dst, int size)  { mitchell_decode(src,dst,size,0x54321076,0x54321076,0x4854,0x4f); }
qtono1_decode(uint8_t * src,uint8_t * dst,int size)183 void qtono1_decode(uint8_t *src, uint8_t *dst, int size)   { mitchell_decode(src,dst,size,0x12345670,0x12345670,0x1111,0x11); }
qsangoku_decode(uint8_t * src,uint8_t * dst,int size)184 void qsangoku_decode(uint8_t *src, uint8_t *dst, int size) { mitchell_decode(src,dst,size,0x23456701,0x23456701,0x1828,0x18); }
block_decode(uint8_t * src,uint8_t * dst,int size)185 void block_decode(uint8_t *src, uint8_t *dst, int size)    { mitchell_decode(src,dst,size,0x02461357,0x64207531,0x0002,0x01); }
186 
187 
cps1_decode(uint8_t * src,uint8_t * dst,int swap_key1,int swap_key2,int addr_key,int xor_key)188 static void cps1_decode(uint8_t *src, uint8_t *dst,int swap_key1,int swap_key2,int addr_key,int xor_key)
189 {
190 	kabuki_decode(src,dst,src,0x0000,0x8000, swap_key1,swap_key2,addr_key,xor_key);
191 }
192 
wof_decode(uint8_t * src,uint8_t * dst)193 void wof_decode(uint8_t *src, uint8_t *dst)      { cps1_decode(src,dst,0x01234567,0x54163072,0x5151,0x51); }
dino_decode(uint8_t * src,uint8_t * dst)194 void dino_decode(uint8_t *src, uint8_t *dst)     { cps1_decode(src,dst,0x76543210,0x24601357,0x4343,0x43); }
punisher_decode(uint8_t * src,uint8_t * dst)195 void punisher_decode(uint8_t *src, uint8_t *dst) { cps1_decode(src,dst,0x67452103,0x75316024,0x2222,0x22); }
slammast_decode(uint8_t * src,uint8_t * dst)196 void slammast_decode(uint8_t *src, uint8_t *dst) { cps1_decode(src,dst,0x54321076,0x65432107,0x3131,0x19); }
197