|
SASC
DVBSoftCAM
|
00001 00002 #include <stdlib.h> 00003 #include <stdio.h> 00004 00005 #include "crypto.h" 00006 #include "data.h" 00007 #include "system-common.h" 00008 #include "systems/nagra/nagra2.h" 00009 00010 #include "compat.h" 00011 00012 static const unsigned char key3des[16] = { }; 00013 00014 static cN2Prov *emmP=0; 00015 00016 void Emm(unsigned char *emmdata, int cmdLen, int id) 00017 { 00018 if(!emmP || (emmP && !emmP->CanHandle(id))) { 00019 delete emmP; 00020 emmP=cN2Providers::GetProv(id,N2FLAG_NONE); 00021 if(emmP) emmP->PrintCaps(L_SYS_EMM); 00022 } 00023 if(emmP) emmP->PostDecrypt(false); 00024 00025 HEXDUMP(L_SYS_RAWEMM,emmdata,cmdLen,"Nagra2 RAWEMM"); 00026 id=(emmdata[8]<<8)+emmdata[9]; 00027 LBSTARTF(L_SYS_EMM); 00028 bool contFail=false; 00029 for(int i=8+2+4+4; i<cmdLen-22; ) { 00030 switch(emmdata[i]) { 00031 case 0x42: // plain Key update 00032 if((((emmdata[i+3]|0xF3)+1)&0xFF) != 0) { 00033 int len=emmdata[i+2]; 00034 int off=emmdata[i+5]; 00035 int ulen=emmdata[i+6]; 00036 if(len>0 && ulen>0 && off+ulen<=len) { 00037 int ks=emmdata[i+3], kn; 00038 if(ks==0x06 || ks==0x46) kn=(ks>>6)&1; else kn=MBC(N2_MAGIC,ks); 00039 unsigned char key[256]; 00040 memset(key,0,sizeof(key)); 00041 bool ok=false; 00042 if((emmdata[i+1]&0x7F)==0) ok=true; 00043 else { 00044 if(emmP && emmP->HasFlags(N2FLAG_POSTAU)) { 00045 if(emmP->PostProcAU(id,&emmdata[i])) ok=true; 00046 } 00047 else PRINTF(L_SYS_EMM,"POSTAU for provider %04x not supported",id); 00048 } 00049 if(ok) { 00050 printf("key %x: off=%x ulen=%x ",kn,off,ulen); 00051 SDump(&emmdata[i+7],ulen); 00052 } 00053 i+=ulen; 00054 } 00055 else PRINTF(L_SYS_EMM,"nano42 key size mismatch len=%d off=%d ulen=%d",len,off,ulen); 00056 } 00057 else PRINTF(L_SYS_EMM,"nano42 0xf3 status exceeded"); 00058 i+=7; 00059 break; 00060 case 0xE0: // DN key update 00061 if(emmdata[i+1]==0x25) { 00062 printf("key%02x: ",(emmdata[i+16]&0x40)>>6); 00063 SDump(&emmdata[i+23],16); 00064 } 00065 i+=emmdata[i+1]+2; 00066 break; 00067 case 0x83: // change data prov. id 00068 id=(emmdata[i+1]<<8)|emmdata[i+2]; 00069 i+=3; 00070 break; 00071 case 0xB0: case 0xB1: case 0xB2: case 0xB3: // Update with ROM CPU code 00072 case 0xB4: case 0xB5: case 0xB6: case 0xB7: 00073 case 0xB8: case 0xB9: case 0xBA: case 0xBB: 00074 case 0xBC: case 0xBD: case 0xBE: case 0xBF: 00075 { 00076 int bx=emmdata[i]&15; 00077 if(!emmP || !emmP->HasFlags(N2FLAG_Bx)) { 00078 PRINTF(L_SYS_EMM,"B%X for provider %04x not supported",bx,id); 00079 i=cmdLen; 00080 break; 00081 } 00082 int r; 00083 if((r=emmP->ProcessBx(emmdata,cmdLen,i+1))>0) 00084 i+=r; 00085 else { 00086 PRINTF(L_SYS_EMM,"B%X executing failed for %04x",bx,id); 00087 i=cmdLen; 00088 } 00089 break; 00090 } 00091 case 0xA4: i+=emmdata[i+1]+2+4; break; // conditional (always no match assumed for now) 00092 case 0xA6: i+=15; break; 00093 case 0xAA: i+=emmdata[i+1]+5; break; 00094 case 0xAD: i+=emmdata[i+1]+2; break; 00095 case 0xA2: 00096 case 0xAE: i+=11;break; 00097 case 0x12: i+=emmdata[i+1]+2; break; // create tier 00098 case 0x20: i+=19; break; // modify tier 00099 case 0x9F: i+=6; break; 00100 case 0xE3: // Eeprom update 00101 { 00102 int ex=emmdata[i]&15; 00103 if(!emmP || !emmP->HasFlags(N2FLAG_Ex)) { 00104 i+=emmdata[i+4]+5; 00105 PRINTF(L_SYS_EMM,"E%X for provider %04x not supported",ex,id); 00106 break; 00107 } 00108 int r; 00109 if((r=emmP->ProcessEx(emmdata,cmdLen,i+1))>0) 00110 i+=r; 00111 else { 00112 PRINTF(L_SYS_EMM,"E%X executing failed for %04x",ex,id); 00113 i=cmdLen; 00114 } 00115 break; 00116 } 00117 case 0xE1: 00118 case 0xE2: 00119 case 0x00: i=cmdLen; break; // end of processing 00120 default: 00121 if(!contFail) LBPUT("unknown EMM nano"); 00122 LBPUT(" %02x",emmdata[i]); 00123 contFail=true; 00124 i++; 00125 continue; 00126 } 00127 LBFLUSH(); contFail=false; 00128 } 00129 LBEND(); 00130 } 00131 00132 bool Ecm(unsigned char *buff, int cmdLen, int id) 00133 { 00134 unsigned char cw[16]; 00135 00136 cN2Prov *ecmP=cN2Providers::GetProv(id,N2FLAG_NONE); 00137 if(ecmP) ecmP->PrintCaps(L_SYS_ECM); 00138 if(ecmP) ecmP->PostDecrypt(true); 00139 00140 int l=0, mecmAlgo=0; 00141 for(int i=(buff[14]&0x10)?16:20; i<cmdLen-10 && l!=3; ) { 00142 printf("%02x: nano %02x\n",i,buff[i]); 00143 switch(buff[i]) { 00144 case 0x10: 00145 case 0x11: 00146 if(buff[i+1]==0x09) { 00147 int s=(~buff[i])&1; 00148 mecmAlgo=buff[i+2]&0x60; 00149 memcpy(cw+(s<<3),&buff[i+3],8); 00150 i+=11; l|=(s+1); 00151 } 00152 else { 00153 printf("bad length %d in CW nano %02x\n",buff[i+1],buff[i]); 00154 i++; 00155 } 00156 break; 00157 case 0x00: 00158 i+=2; break; 00159 case 0x13 ... 0x15: 00160 i+=4; break; 00161 case 0x30 ... 0x36: 00162 case 0xB0: 00163 i+=buff[i+1]+2; 00164 break; 00165 default: 00166 i++; 00167 continue; 00168 } 00169 } 00170 if(l!=3) return false; 00171 if(mecmAlgo>0) { 00172 if(ecmP && ecmP->HasFlags(N2FLAG_MECM)) { 00173 static unsigned char odata[15] = { 0x80,0x30,0x47,0x07,0x45,0xec,0xc1,0xee,0xc5,0x53,0x91,0x2f,0x70,0x34,0x34 }; 00174 if(!ecmP->MECM(buff[15],mecmAlgo,odata,cw)) return false; 00175 } 00176 else { printf("MECM for provider %04x not supported\n",id); return false; } 00177 } 00178 if(ecmP) ecmP->SwapCW(cw); 00179 printf("resulting CW: "); SDump(cw,16); 00180 return true; 00181 } 00182 00183 int main(int argc, char *argv[]) 00184 { 00185 if(argc<5) { 00186 printf("usage: %s <plugin-dir> <id> <ECM/EMM> <raw-file> [<raw-file> [..]]\n",argv[0]); 00187 return 1; 00188 } 00189 00190 int mode; 00191 if(!strcasecmp(argv[3],"ECM")) mode=1; 00192 else if(!strcasecmp(argv[3],"EMM")) mode=2; 00193 else { 00194 printf("bad mode '%s'\n",argv[3]); 00195 return 1; 00196 } 00197 00198 InitAll(argv[1]); 00199 LogAll(); 00200 cLogging::SetModuleOption(LCLASS(L_SYS,L_SYS_DISASM),false); 00201 00202 int id=strtol(argv[2],0,0); 00203 int dlen=(mode==1) ? 64 : 96; 00204 unsigned char data[4096]; 00205 for(int pos=4; pos<argc; pos++) { 00206 int len=ReadRaw(argv[pos],data,sizeof(data)); 00207 if(len%dlen != 0) { printf("bad raw file format\n"); exit(1); } 00208 00209 for(int alen=0; alen<len; alen+=dlen) { 00210 if(mode==1) Ecm(&data[alen],dlen,id); 00211 else if(mode==2) Emm(&data[alen],dlen,id); 00212 } 00213 } 00214 }