SASC-NG
DVBSoftCAM

testN2Emu.c

Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines