void cSystemIrd2::ProcessEMM(int pid, int caid, const unsigned char *data) { int prov=0; //XXX how to get provider here?? int len=SCT_LEN(data); unsigned char *emm=AUTOMEM(len); cPlainKey *pk; if(!(pk=keys.FindKey('I',caid,KEYSET(prov,TYPE_IV,0),16))) { PRINTF(L_SYS_EMM,"missing %04x %02x IV key",caid,prov); return; } unsigned char EMM_IV[16]; pk->Get(EMM_IV); for(int keyno=0; keyno<2; keyno++) { if(!(pk=keys.FindKey('I',caid,KEYSET(prov,TYPE_PMK,keyno),16))) { PRINTF(L_SYS_EMM,"missing %04x %02x MK%d key",caid,prov,keyno); continue; } unsigned char PMK[16]; pk->Get(PMK); if(!(pk=keys.FindKey('I',caid,KEYSET(prov,TYPE_SEED,1),16))) { PRINTF(L_SYS_EMM,"missing %04x %02x EMM key",caid,prov); return; } unsigned char EMM_Seed[16]; pk->Get(EMM_Seed); PrepareSeed(EMM_Seed,PMK); memcpy(emm,data,len); Decrypt(&emm[10],EMM_IV,EMM_Seed,len-10); NanoDecrypt(emm,16,len-8,PMK,EMM_IV); memmove(emm+6,emm+7,len-7); // removing padding byte if(CalculateHash(EMM_Seed,EMM_IV,emm+3,len-4)) { HEXDUMP(L_SYS_RAWEMM,emm,len,"Irdeto2 RAWEMM"); for(int i=15; i<len-9;) { int l=NANOLEN(emm[i+1]); switch(emm[i]) { case 0x10: case 0x50: if(l==0x13 && i+l<=len-9) { FoundKey(); if(keys.NewKey('I',caid,KEYSET(prov,TYPE_OP,emm[i+2]>>2),&emm[i+3],16)) NewKey(); } break; } i+=l; } break; }
int cProviderViaccess::Assemble(cAssembleData *ad) { const unsigned char *data=ad->Data(); int len=SCT_LEN(data); switch(data[0]) { case 0x8C: case 0x8D: if(data[0]!=sharedToggle) { free(sharedEmm); sharedLen=len; sharedEmm=(unsigned char *)malloc(len); if(sharedEmm) memcpy(sharedEmm,data,sharedLen); sharedToggle=data[0]; } break; case 0x8E: if(sharedEmm) { unsigned char *tmp=AUTOMEM(len+sharedLen); unsigned char *ass=(unsigned char *)cParseViaccess::NanoStart(data); len-=(ass-data); if((data[6]&2)==0) { const int addrlen=len-8; len=0; tmp[len++]=0x9e; tmp[len++]=addrlen; memcpy(&tmp[len],&ass[0],addrlen); len+=addrlen; tmp[len++]=0xf0; tmp[len++]=0x08; memcpy(&tmp[len],&ass[addrlen],8); len+=8; } else { memcpy(tmp,ass,len); } ass=(unsigned char *)cParseViaccess::NanoStart(sharedEmm); int l=sharedLen-(ass-sharedEmm); memcpy(&tmp[len],ass,l); len+=l; ass=(unsigned char *)malloc(len+7); if(ass) { memcpy(ass,data,7); SortNanos(ass+7,tmp,len); SetSctLen(ass,len+4); ad->SetAssembled(ass); return 1; // assembled } } break; } return -1; // ignore }
int cCardCryptoworks::Assemble(cAssembleData *ad) { const unsigned char *data=ad->Data(); int len=SCT_LEN(data); switch(data[0]) { case 0x82: return 0; // no assemble needed case 0x84: free(sharedEmm); sharedEmm=(unsigned char *)malloc(len); if(sharedEmm) { memcpy(sharedEmm,data,len); sharedLen=len; } break; case 0x86: if(sharedEmm) { int alen=len-5 + sharedLen-12; unsigned char *tmp=AUTOMEM(alen); memcpy(tmp,&data[5],len-5); memcpy(tmp+len-5,&sharedEmm[12],sharedLen-12); unsigned char *ass=(unsigned char *)malloc(alen+12); if(!ass) return -1; // ignore memcpy(ass,sharedEmm,12); SortNanos(ass+12,tmp,alen); SetSctLen(ass,alen+9); free(sharedEmm); sharedEmm=0; if(ass[11]==alen) { // sanity check ad->SetAssembled(ass); return 1; // assembled } } break; case 0x88: case 0x89: if(data[0]!=globalToggle) { globalToggle=data[0]; unsigned int crc=crc32_le(0,data+1,len-1); if(crc!=globalCrc) { globalCrc=crc; return 0; // no assemble needed } } break; } return -1; // ignore }
bool cSmartCardDataNagra::Parse(const char *line) { bool isSK=false; int dlen=64; BN_set_word(exp,3); line=skipspace(line); unsigned char id[4]; if(GetHex(line,id,sizeof(id))!=sizeof(id)) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: card id"); return false; } cardid=UINT32_BE(id); line=skipspace(line); if(!strncasecmp(line,"SK",2)) { isSK=true; dlen=96; line+=2; } else { if(GetHex(line,bk,sizeof(bk))!=sizeof(bk)) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: boxkey"); return false; } line=skipspace(line); if(!strncasecmp(line,"IRDMOD",6)) { isIrdMod=true; line+=6; } else if(!strncasecmp(line,"CARDMOD",7)) { isIrdMod=false; line+=7; } else { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: IRDMOD/CARDMOD"); return false; } } line=skipspace(line); unsigned char *buff=AUTOMEM(dlen); if(GetHex(line,buff,dlen)!=dlen) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: data block"); return false; } if(!isSK) { mod.Get(buff,64); } else { struct SecondaryKey *sk=(struct SecondaryKey *)buff; if(UINT16_BE(sk->cs)!=CRC16(buff,sizeof(*sk)-sizeof(sk->cs),false)) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: secondary key CRC failed"); return false; } unsigned short e=UINT16_BE(sk->exp); if(e!=0x0003 && e!=CRC16(buff,12,false)) BN_set_word(exp,e); xxor(bk,sizeof(bk),sk->y1,sk->y2); mod.Get(sk->mod,sizeof(sk->mod)); } return true; }