diff --git a/cic/d411-seeds.txt b/cic/d411-seeds.txt new file mode 100644 index 0000000..a745020 --- /dev/null +++ b/cic/d411-seeds.txt @@ -0,0 +1,6 @@ +key seed: b14f4b57fd61e98 + 110101111101010 + +lck seed: _9a185f11e10dec + _10101111010100 + diff --git a/cic/d411.pseudo b/cic/d411.pseudo new file mode 100644 index 0000000..cfe8518 --- /dev/null +++ b/cic/d411.pseudo @@ -0,0 +1,230 @@ +map: + +RAM:0x01~0x0f Seed 1 (own key seed)? +RAM:0x10 send/receive buffer? +RAM:0x11 Stream ID received from LOCK +RAM:0x12~0x1f Seed 2 (Stream ID part of lock seed)? + +main: + goto initstream; + +mainloop: + a=0x1; +mainloop2: + x=a; + for(x=a; x<16; x++) { + main_inner1: + bm=0x0; + call 34b(0x00+x) // prepare next stream bit (send) + bm=0x1; + call 34b(0x10+x) // prepare next stream bit (recv) + call 131 // bm=1; bl=0; a=P0 + a=P0; + if(P0.0) die; // WTF? P0.0 is an output! + if(P0.1) die; + + a=0x0; + a<->RAM[0x10]; // load A with next output stream bit (nibble) + P0=a; // LSB -> Key output + nop; // wait + a=P0; // read from lock + P0=0; // clear output port + RAM[0x10]=a; // store next input stream bit in RAM + bl=3; a=P3 // P3.0, which is usually UNCONNECTED, + // somehow determines how to deal with + // the input stream. This is SNES CIC specific. + // NOTE: For commonly used key operation / pin mapping we must assume + // that P3.0 is HIGH (1). (otherwise the key would die immediately) + bl=0 + if(P3.0){ + if(RAM[0x10].1) { // input stream bit set? + call 159 // bm=0; bl=0; a=P0 // switch "bank" + if(RAM[0x00].0) { // matches calculated bit? + goto 13d // then go on + } else goto 157 // DIE // else gtfo + } else goto input_stream_bit_clear // input stream bit clear, check + } else goto 175 + + input_stream_bit_clear: // input stream bit cleared + call 159 // bm=0; bl=0; a=P0 // switch "bank" + if(RAM[0x00].0) { // calculated bit doesn't match? + goto 157 // DIE // then die + } else goto 17a // nop; goto 13d // else go on + + 175: + if(RAM[0x10].0) { // this is essentially the same + call 159 // bm=0; bl=0; a=P0 // as above but + if(RAM[0x00].1) { // input stream bit is set in + goto 13d; // RAM[0x10].0 instead of .1 and + } else goto 157 // DIE // calculated from RAM[0x00].1 + } else { // instead of .0, if P3.0 is 0. + call 159 // bm=0; bl=0; a=P0 + if(RAM[0x00].1) { + goto 157 // DIE + } else goto 17a // nop; goto 13d + } + + 13d: // continue + a=x; + a++; // loop to next of 15 stream + if(!overflow) { // bits, afterwards: + x=a; + goto main_inner1; + } + } // for x=1 to 15 + (x=0) // + call 04a // set Resets (dummy for key mode) // output reset levels + call 370 // "MANGLE BOTH" // calculate new seeds + call 370 // "MANGLE BOTH" // for both sides + call 370 // "MANGLE BOTH" // (lock+key) to exchange + // this is "SNES security": MANGLE is called THREE TIMES! + // as opposed to only once on the NES CICs. + a=RAM[0x13]; + RAM[0x13]=RAM[0x17]; + // set P3.0 to LSB of RAM[0x13] + P3 = (P3 & 0xe) | (RAM[0x13] & 0x1); + if(a.0==1) { + goto mainloop (seed offset=0x1) + } else goto mainloop2 (seed offset=a) + + +04a: // "RUN HOST" + call 37a // "skip if lock" + a=0x0; + P1=a; + nop + nop + nop + P1=a; +return + +mangle_both: + call mangle(bm=0); + goto mangle(bm=1); + +mangle: + bl=0xf; + a=RAM[bm:0xf]; + x=a; + carry=1; + bl=0x1; + a+=RAM[bm:0x1]+1; + RAM[bm:0x1]=a; + ==> RAM[bm:0x1]+=RAM[bm:0xf]+1; + a=RAM[bm:0x1]; bl++; + a+=RAM[bm:0x2]+1; + a=~a; + RAM[bm:0x2]=a; bl++; + a+=RAM[bm:0x3]+1; + if(!overflow) { + RAM[bm:0x3]=a; bl++; + } + a+=RAM[bm:0x4]; + RAM[bm:0x4]=a; + a=RAM[bm:0x4]; bl++; + carry=0; + a+=RAM[bm:0x5]+0; + RAM[bm:0x5]=a; bl++; + a+=8; + a+=RAM[bm:0x6]+0; + RAM[bm:0x6]=a; bl++; +mangle_inner1: + a++; + nop + a+=RAM[bm:0x7..0xf]+0; + RAM[bm:0x7..0xf]=a; + a=RAM[bm:0x7..0xf]; bl++; + if(!overflow) goto mangle_inner1 + a<->x; + a+=0xf; + if(!overflow) return; + goto mangle + +131: + bm=0x0; + call 37a + (if(!lock)bm=1); +return; + +37a: + +34b: input x='bl' + // take a nibble out of the seed (indexed by bm:x) + // and set [bm:0], i.e. RAM[0x00] or RAM[0x10] like this: + // if(seednibble&1) { + // result=0b0000; + // } else { + // if(P3.0) { + // result=0b0101; + // } else { + // result=0b0010; + // } + // } + bl=x; + a=RAM[bm:x]; + RAM[bm:0] = RAM[bm:x].0 ? 0x7 : 0x0; + + a=P3; // WTF is P3???? + bl=0; + if (P3.0==1) { + RAM[bm:0] &= 0b1101; + } else { + RAM[bm:0] &= 0b1010; + } +return + +initstream: +if(P0.3==0) { + if(P0.3==0) { + A=RAM[0x11]; RAM[0x11]=0xf + input_stream_id_bit; + if !(A.1) RAM[0x11]&=0b0111 + input_stream_id_bit; + if !(A.1) RAM[0x11]&=0b1110 + input_stream_id_bit; + if !(A.1) RAM[0x11]&=0b1101 + input_stream_id_bit; + if !(A.1) RAM[0x11]&=0b1011 + nop + + RAM[0x01]=0xb; + RAM[0x02]=0x1; + RAM[0x03]=0x4; + RAM[0x04]=0xf; + RAM[0x05]=0x4; + RAM[0x06]=0xb; // 0x6???? + RAM[0x07]=0x5; + RAM[0x08]=0x7; // 0x8???? + RAM[0x09]=0xf; + RAM[0x0a]=0xd; // 0xa???? + RAM[0x0b]=0x6; + RAM[0x0c]=0x1; // 0xc???? + RAM[0x0d]=0xe; + RAM[0x0e]=0x9; + RAM[0x0f]=0x8; + + RAM[0x12]=0x9; + RAM[0x13]=0xa; + RAM[0x14]=0x1; + RAM[0x15]=0x8; + RAM[0x16]=0x5; + RAM[0x17]=0xf; // 0x7???? + RAM[0x18]=0x1; + RAM[0x19]=0x1; // 0x9???? + RAM[0x1a]=0xe; + RAM[0x1b]=0x1; // 0xb???? + RAM[0x1c]=0x0; + RAM[0x1d]=0xd; + RAM[0x1e]=0xe; + RAM[0x1f]=0xc; + + mainloop; + } +} + + + +input_stream_id_bit: + wait 6 cycles + A=P0 +ret diff --git a/cic/mangle.c b/cic/mangle.c new file mode 100644 index 0000000..03ad93d --- /dev/null +++ b/cic/mangle.c @@ -0,0 +1,103 @@ +#include + +void printseed(unsigned char* data) { + int i; + for(i=1;i<16;i++) { + printf("%x ", data[i]); + } + printf("\n"); +} + +void printstream(unsigned char* data, int restart) { + int i; + for(i=restart;i<16;i++) { + printf("%d ", data[i]&1); + } + printf("\n"); +} +#define CARRY if(a>0x0f) {\ + a &= 0xf;\ + carry=1;\ + } else carry=0; + +void mangle(unsigned char* data) { + unsigned char a,x,temp,i,offset,carry=0; + a=data[0xf]; + do { + x=a; + offset=1; + carry=1; + a+=data[offset]+carry; + data[offset]=a&0xf; + a=data[offset++]; + a+=data[offset]+carry; + a=(~a)&0xf; + temp=a; a=data[offset]; data[offset++]=temp&0xf; + a+=data[offset]+carry; + if(a<0x10) { + temp=a; a=data[offset]; data[offset++]=temp&0xf; + } + a+=data[offset]; + data[offset]=a&0xf; + a=data[offset++]; + carry=0; + a+=data[offset]+carry; + temp=a; a=data[offset]; data[offset++]=temp&0xf; + a+=8; + if(a<0x10) { + a+=data[offset]+carry; + } + temp=a; a=data[offset]; data[offset++]=temp&0xf; + + while(offset<0x10) { + a++; + a+=data[offset]+carry; + data[offset]=a&0xf; + a=data[offset++]; + } + offset &= 0xf; + a=x; + a+=0xf; + CARRY + } while(carry); +} + +int main(void) { + unsigned char restart=1; + unsigned char keyseed_orig[16]= {0x0, // dummy + 0xb,0x1,0x4,0xf, + 0x4,0xb,0x5,0x7, + 0xf,0xd,0x6,0x1, + 0xe,0x9,0x8}; + unsigned char lockseed_orig[16]={0x0, // dummy + 0x0,0x9,0xa,0x1, + 0x8,0x5,0xf,0x1, + 0x1,0xe,0x1,0x0, + 0xd,0xe,0xc}; + + unsigned char keyseed[16]; + unsigned char lockseed[16]; + + printseed(keyseed); + printseed(lockseed); + printf("\n"); + +while(1) { + printf("\n"); + printstream(keyseed, restart); + mangle(keyseed); + mangle(keyseed); + mangle(keyseed); + mangle(lockseed); + mangle(lockseed); + mangle(lockseed); + +// printseed(keyseed); +// printseed(lockseed); + restart=lockseed[3]; + lockseed[3]=lockseed[7]; + if(!restart)restart=1; +// printf("send %d-15\n", restart); +} + return 0; +} diff --git a/cic/scramble.txt b/cic/scramble.txt new file mode 100644 index 0000000..1a48b02 --- /dev/null +++ b/cic/scramble.txt @@ -0,0 +1,70 @@ +start: +b14f4b57fd61e98 +4953771997e11b4 + BL=f +A=[f]=8 +X=A + C=1 + BL=1 +A+=[1]+1 = 8+b+1 = 4 C=1 +store [1]=4 +A=[1]=4 BL=2 +A+=[2]+1 = 4+1+1 = 6 C=0 +A=~A = 9 +A=[2] = 1 +store [2]=9 BL=3 +A+=[3]+0 = 4+1+0 = 5 C=0; no skip +A=[3] = 4 +store [3]=5 BL=4 +A+=[4] = 4+f = 3 C=1 +store [4]=3 +A=[4] = 3 BL=5 + C=0 +A+=[5]+1 = 3+4+0 = 7 C=0 +A=[5] = 4 +store [5]=7 BL=6 +A+=8 = 4+8 = c C=0 +A+=[6]+0 = b+c+0 = 7 C=1 +A=[6] = b +store [6]=7 BL=7 + +A+=1 = b+1 = c C=0 +A+=[7]+0 = c+5+0 = 1 C=1 +store [7] = 1 +A=[7] = 1 BL=8 +A+=1 = 1+1 = 2 C=0 +A+=[8]+0 = 2+7+0 = 9 C=0 +store [8] = 9 +A=[8] = 9 BL=9 +A+=1 = 9+1 = a C=0 +A+=[9]+0 = a+f+0 = 9 C=1 +store [9] = 9 +A=[9] = 9 BL=a +A+=1 = 9+1 = a C=0 +A+=[a]+0 = a+d+0 = 7 C=1 +store [a] = 7 +A=[a] = 7 BL=b +A+=1 = 7+1 = 8 C=0 +A+=[b]+0 = 8+6+0 = e C=0 +store [b] = e +A=[b] = e BL=c +A+=1 = e+1 = f C=0 +A+=[c]+0 = f+1+0 = 0 C=1 +store [c] = 0 +A=[c] = 0 BL=d +A+=1 = 0+1 = 1 C=0 +A+=[d]+0 = 1+e+0 = f C=0 +store [d] = f +A=[d] = f BL=e +A+=1 = f+1 = 0 C=1 +A+=[e]+1 = 0+9+1 = a C=0 +store [e] = a +A=[e] = a BL=f +A+=1 = a+1 = b C=0 +A+=[f]+0 = b+8+0 = 3 C=1 +store [f] = 3 +A=[f] = 3 BL=0; skip +A=X=8 +A+=f = 8+f = 7 C=1; skip +noooo, all the shit again +