|
SASC-NG
DVBSoftCAM
|
00001 /* 00002 * Softcam plugin to VDR (C++) 00003 * 00004 * This code is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This code is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00018 */ 00019 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <ctype.h> 00023 #include <byteswap.h> 00024 00025 #include "system-common.h" 00026 #include "data.h" 00027 #include "helper.h" 00028 #include "crypto.h" 00029 #include "misc.h" 00030 #include "log-sys.h" 00031 #include "version.h" 00032 00033 SCAPIVERSTAG(); 00034 00035 #define SYSTEM_CRYPTOWORKS 0x0D00 00036 00037 #define SYSTEM_NAME "Cryptoworks" 00038 #define SYSTEM_PRI -10 00039 #define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_CRYPTOWORKS) 00040 00041 #define L_SYS 4 00042 #define L_SYS_ALL LALL(L_SYS_LASTDEF) 00043 00044 static const struct LogModule lm_sys = { 00045 (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK, 00046 (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK, 00047 "cryptoworks", 00048 { L_SYS_DEFNAMES } 00049 }; 00050 ADD_MODULE(L_SYS,lm_sys) 00051 00052 #define DUMPNANO(t,p,n) \ 00053 LBSTART(L_SYS_VERBOSE); \ 00054 LBPUT("%s",(t)); \ 00055 unsigned char *__p=(unsigned char *)(p); \ 00056 int __n=(n); \ 00057 for(int i=0; i<__n;) { \ 00058 LBFLUSH(); \ 00059 LBPUT("%02X %02X -",__p[i],__p[i+1]); \ 00060 i+=2; \ 00061 for(int l=__p[i-1]; l>0; l--) { LBPUT(" %02X",__p[i]); i++; }\ 00062 if(i>__n) { LBFLUSH(); LBPUT("length exceeded %d != %d",i,__n); } \ 00063 } \ 00064 LBEND(); 00065 00066 // -- cCwDes ------------------------------------------------------------------- 00067 00068 static const unsigned char cryptoPC1[] = { 00069 53,46,39,32,50,43,36,29, 00070 22,15, 8, 1,51,44,37,30, 00071 23,16, 9, 2,52,45,38,31, 00072 24,17,10, 3,53,46,39,32, 00073 25,18,11, 4,56,49,42,35, 00074 28,21,14, 7,55,48,41,34, 00075 27,20,13, 6,54,47,40,33, 00076 26,19,12, 5,25,18,11, 4 00077 }; 00078 00079 static const unsigned char cryptoPC2[] = { 00080 18,21,15,28, 5, 9, 7,32,19,10,25,14, 00081 27,23,16, 8,30,12, 20,11,31,24,17, 6, 00082 49,60,39,45,55,63, 38,48,59,53,41,56, 00083 52,57,47,64,42,61, 54,50,58,44,37,40, 00084 }; 00085 00086 #define shiftin(V,R,n) ((V<<1)+(((R)>>(n))&1)) 00087 #define rol28(V,n) (V<<(n) | ((V&0x0fffffffL)>>(28-(n)))) 00088 #define ror28(V,n) (V>>(n) | ((V&0xfffffff0L)<<(28-(n)))) 00089 00090 #define DESROUND(C,D,T) { \ 00091 unsigned int s=0; \ 00092 for(int j=7, k=0; j>=0; j--) { \ 00093 unsigned int v=0, K=0; \ 00094 for(int t=5; t>=0; t--, k++) { \ 00095 v=shiftin(v,T,E[k]); \ 00096 if(PC2[k]<33) K=shiftin(K,C,32-PC2[k]); \ 00097 else K=shiftin(K,D,64-PC2[k]); \ 00098 } \ 00099 s=(s<<4) + S[7-j][v^K]; \ 00100 } \ 00101 T=0; \ 00102 for(int j=31; j>=0; j--) T=shiftin(T,s,P[j]); \ 00103 } 00104 00105 class cCwDes : public cDes { 00106 private: 00107 void PrepKey(unsigned char *out, const unsigned char *key) const; 00108 void PrepKey48(unsigned char *out, const unsigned char *key22, unsigned char algo) const; 00109 public: 00110 cCwDes(void); 00111 void CwDes(unsigned char *data, const unsigned char *key22, int mode) const; 00112 void CwL2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const; 00113 void CwR2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const; 00114 }; 00115 00116 cCwDes::cCwDes(void) 00117 :cDes(cryptoPC1,cryptoPC2) 00118 {} 00119 00120 void cCwDes::PrepKey(unsigned char *out, const unsigned char *key) const 00121 { 00122 if(key!=out) memcpy(out,key,8); 00123 Permute(out,PC1,64); 00124 } 00125 00126 void cCwDes::PrepKey48(unsigned char *out, const unsigned char *key22, unsigned char algo) const 00127 { 00128 memset(out,0,8); 00129 memcpy(out,&key22[16],6); 00130 int ctr=7-(algo&7); 00131 for(int i=8; i>=2 && i>ctr; i--) out[i-2]=key22[i]; 00132 } 00133 00134 void cCwDes::CwDes(unsigned char *data, const unsigned char *key22, int mode) const 00135 { 00136 unsigned char mkey[8]; 00137 PrepKey(mkey,key22+9); 00138 LDUMP(L_SYS_VERBOSE,mkey,8,"prepped key DES:"); 00139 unsigned int C=UINT32_BE(mkey ); 00140 unsigned int D=UINT32_BE(mkey+4); 00141 unsigned int L=UINT32_BE(data ); 00142 unsigned int R=UINT32_BE(data+4); 00143 if(!(mode&DES_RIGHT)) { 00144 for(int i=15; i>=0; i--) { 00145 C=rol28(C,LS[15-i]); D=rol28(D,LS[15-i]); 00146 unsigned int T=R; 00147 DESROUND(C,D,T); 00148 T^=L; L=R; R=T; 00149 } 00150 } 00151 else { 00152 for(int i=15; i>=0; i--) { 00153 unsigned int T=R; 00154 DESROUND(C,D,T); 00155 T^=L; L=R; R=T; 00156 C=ror28(C,LS[i]); D=ror28(D,LS[i]); 00157 } 00158 } 00159 BYTE4_BE(data ,L); 00160 BYTE4_BE(data+4,R); 00161 } 00162 00163 void cCwDes::CwL2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const 00164 { 00165 unsigned char mkey[8]; 00166 PrepKey48(mkey,key22,algo); 00167 PrepKey(mkey,mkey); 00168 LDUMP(L_SYS_VERBOSE,mkey,8,"prepped key L2:"); 00169 unsigned int C=UINT32_BE(mkey ); 00170 unsigned int D=UINT32_BE(mkey+4); 00171 unsigned int L=UINT32_BE(data ); 00172 unsigned int R=UINT32_BE(data+4); 00173 for(int i=1; i>=0; i--) { 00174 C=rol28(C,1); D=rol28(D,1); 00175 unsigned int T=R; 00176 DESROUND(C,D,T); 00177 T^=L; L=R; R=T; 00178 PRINTF(L_SYS_VERBOSE,"round %d key L2: %08x %08x",i,C,D); 00179 } 00180 BYTE4_BE(data ,L); 00181 BYTE4_BE(data+4,R); 00182 } 00183 00184 void cCwDes::CwR2Des(unsigned char *data, const unsigned char *key22, unsigned char algo) const 00185 { 00186 unsigned char mkey[8]; 00187 PrepKey48(mkey,key22,algo); 00188 PrepKey(mkey,mkey); 00189 LDUMP(L_SYS_VERBOSE,mkey,8,"prepped key R2:"); 00190 unsigned int C=UINT32_BE(mkey ); 00191 unsigned int D=UINT32_BE(mkey+4); 00192 unsigned int L=UINT32_BE(data ); 00193 unsigned int R=UINT32_BE(data+4); 00194 for(int i=1; i>=0; i--) { 00195 C=rol28(C,15); D=rol28(D,15); 00196 } 00197 for(int i=1; i>=0; i--) { 00198 unsigned int T=R; 00199 DESROUND(C,D,T); 00200 T^=L; L=R; R=T; 00201 C=ror28(C,1); D=ror28(D,1); 00202 } 00203 BYTE4_BE(data ,R); 00204 BYTE4_BE(data+4,L); 00205 } 00206 00207 // -- cCryptoworks ------------------------------------------------------------- 00208 00209 class cCryptoworks { 00210 private: 00211 cCwDes des; 00212 cRSA rsa; 00213 cBN exp; 00214 // 00215 void EncDec(unsigned char *data, const unsigned char *key22, unsigned char algo, int mode); 00216 public: 00217 cCryptoworks(void); 00218 void Signature(const unsigned char *data, int len, const unsigned char *key22, unsigned char *sig); 00219 void DecryptDES(unsigned char *data, unsigned char algo, const unsigned char *key22); 00220 bool DecryptRSA(unsigned char *data, int len, unsigned char algo, const unsigned char *key22, BIGNUM *mod); 00221 }; 00222 00223 cCryptoworks::cCryptoworks(void) 00224 { 00225 BN_set_word(exp,2); 00226 } 00227 00228 void cCryptoworks::EncDec(unsigned char *data, const unsigned char *key22, unsigned char algo, int mode) 00229 { 00230 LDUMP(L_SYS_VERBOSE,data,8,"encdec in :"); 00231 PRINTF(L_SYS_VERBOSE,"algo %d",algo); 00232 LDUMP(L_SYS_VERBOSE,key22,22,"encdec key:"); 00233 des.CwL2Des(data,key22,algo); 00234 des.CwDes(data,key22,mode); 00235 des.CwR2Des(data,key22,algo); 00236 LDUMP(L_SYS_VERBOSE,data,8,"encdec out:"); 00237 } 00238 00239 void cCryptoworks::Signature(const unsigned char *data, int len, const unsigned char *key22, unsigned char *sig) 00240 { 00241 PRINTF(L_SYS_VERBOSE,"sig start"); 00242 int algo=data[0]&7; 00243 if(algo==7) algo=6; 00244 memset(sig,0,8); 00245 int j=0; 00246 bool first=true; 00247 for(int i=0; i<len; i++) { 00248 sig[j]^=data[i]; 00249 if(++j>7) { 00250 LDUMP(L_SYS_VERBOSE,sig,8,"sig buf"); 00251 if(first) { 00252 des.CwL2Des(sig,key22,algo); 00253 LDUMP(L_SYS_VERBOSE,sig,8,"sig -> "); 00254 } 00255 des.CwDes(sig,key22,DES_LEFT); 00256 j=0; first=false; 00257 LDUMP(L_SYS_VERBOSE,sig,8,"sig -> "); 00258 } 00259 } 00260 if(j>0) { 00261 LDUMP(L_SYS_VERBOSE,sig,8,"sig buf final "); 00262 des.CwDes(sig,key22,DES_LEFT); 00263 LDUMP(L_SYS_VERBOSE,sig,8,"sig -> "); 00264 } 00265 des.CwR2Des(sig,key22,algo); 00266 LDUMP(L_SYS_VERBOSE,sig,8,"sig calc "); 00267 } 00268 00269 void cCryptoworks::DecryptDES(unsigned char *data, unsigned char algo, const unsigned char *key22) 00270 { 00271 algo&=7; 00272 if(algo<7) { 00273 EncDec(data,key22,algo,DES_RIGHT); 00274 } 00275 else { 00276 unsigned char k[22], t[8]; 00277 memcpy(k,key22,22); 00278 for(int i=0; i<3; i++) { 00279 EncDec(data,k,algo,i&1); 00280 memcpy(t,k,8); memcpy(k,k+8,8); memcpy(k+8,t,8); 00281 } 00282 } 00283 } 00284 00285 bool cCryptoworks::DecryptRSA(unsigned char *data, int len, unsigned char algo, const unsigned char *key22, BIGNUM *mod) 00286 { 00287 unsigned char buf[64], *mask=AUTOMEM(len); 00288 00289 LDUMP(L_SYS_VERBOSE,data+len,8,"rsa in:"); 00290 memcpy(buf,data+len,8); 00291 EncDec(buf,key22,algo,DES_LEFT); 00292 buf[0]|=0x80; 00293 if((algo&0x18)<0x18) buf[0]=0xFF; 00294 if(algo&8) buf[1]=0xFF; 00295 LDUMP(L_SYS_VERBOSE,buf,8,"rsa seed:"); 00296 00297 static const unsigned char t1[] = { 0xE,0x3,0x5,0x8,0x9,0x4,0x2,0xF,0x0,0xD,0xB,0x6,0x7,0xA,0xC,0x1 }; 00298 for(int k=0; k<len; k+=32) { 00299 memcpy(buf+8,buf,8); 00300 for(int i=0; i<8; i++) { 00301 int n=i<<1; 00302 buf[n+1]=buf[i+8]; 00303 buf[n ]=(t1[buf[n+1]>>4]<<4) | t1[buf[i+8]&0xF]; 00304 LDUMP(L_SYS_VERBOSE,buf,16,"rsa buf:"); 00305 } 00306 for(int i=16; i<64; i+=16) memcpy(&buf[i],buf,16); 00307 buf[31]=((buf[15]<<4)&0xFF) | 6; 00308 buf[16]=buf[0]^1; 00309 buf[32]&=0x7F; 00310 buf[32]|=0x40; 00311 RotateBytes(buf,32); 00312 RotateBytes(buf+32,32); 00313 LDUMP(L_SYS_VERBOSE,buf,64,"rsa data:"); 00314 00315 if(rsa.RSA(buf,buf,64,exp,mod,true)==0) { 00316 PRINTF(L_SYS_CRYPTO,"RSA failed"); 00317 return false; 00318 } 00319 RotateBytes(buf,8); 00320 RotateBytes(mask+k,buf+8,min(32,len-k)); 00321 } 00322 LDUMP(L_SYS_VERBOSE,mask,len,"rsa out:"); 00323 00324 xxor(data,len,data,mask); 00325 return true; 00326 } 00327 00328 // -- cPlainKeyCryptoworks ----------------------------------------------------- 00329 00330 #define PLAINLEN_CW_D 16 00331 #define PLAINLEN_CW_CC 6 00332 #define PLAINLEN_CW_R 64 00333 00334 #define CCTYP 0x00 00335 #define CCID 0xFF 00336 00337 #define PROV(keynr) (((keynr)>>16)&0xFF) 00338 #define TYPE(keynr) (((keynr)>> 8)&0xFF) 00339 #define ID(keynr) (((keynr) )&0xFF) 00340 #define KEYSET(prov,typ,id) ((((prov)&0xFF)<<16)|(((typ)&0xFF)<<8)|((id)&0xFF)) 00341 00342 class cPlainKeyCryptoworks : public cDualKey { 00343 protected: 00344 virtual bool IsBNKey(void) const; 00345 virtual int IdSize(void) { return 4; } 00346 virtual cString PrintKeyNr(void); 00347 public: 00348 cPlainKeyCryptoworks(bool Super); 00349 virtual bool Parse(const char *line); 00350 }; 00351 00352 static cPlainKeyTypeReg<cPlainKeyCryptoworks,'W'> KeyReg; 00353 00354 cPlainKeyCryptoworks::cPlainKeyCryptoworks(bool Super) 00355 :cDualKey(Super,true) 00356 {} 00357 00358 bool cPlainKeyCryptoworks::IsBNKey(void) const 00359 { 00360 return TYPE(keynr)==0x10; 00361 } 00362 00363 bool cPlainKeyCryptoworks::Parse(const char *line) 00364 { 00365 unsigned char sid[2], sprov; 00366 if(GetChar(line,&type,1) && GetHex(line,sid,2) && GetHex(line,&sprov,1)) { 00367 int keylen, prov; 00368 type=toupper(type); id=Bin2Int(sid,2); prov=sprov; 00369 line=skipspace(line); 00370 bool ok; 00371 if(!strncasecmp(line,"CC",2)) { // cardkey 00372 keynr=KEYSET(prov,CCTYP,CCID); 00373 keylen=PLAINLEN_CW_CC; 00374 line+=2; 00375 ok=true; 00376 } 00377 else { 00378 unsigned char sid, styp; 00379 ok=GetHex(line,&styp,1) && GetHex(line,&sid,1); 00380 keynr=KEYSET(prov,styp,sid); 00381 keylen=IsBNKey() ? PLAINLEN_CW_R : PLAINLEN_CW_D; 00382 } 00383 if(ok) { 00384 unsigned char *skey=AUTOMEM(keylen); 00385 if(GetHex(line,skey,keylen)) { 00386 SetBinKey(skey,keylen); 00387 return true; 00388 } 00389 } 00390 } 00391 return false; 00392 } 00393 00394 cString cPlainKeyCryptoworks::PrintKeyNr(void) 00395 { 00396 int prov=PROV(keynr); 00397 int keytyp=TYPE(keynr); 00398 int keyid=ID(keynr); 00399 return cString::sprintf(keytyp==CCTYP && keyid==CCID ? "%02X CC":"%02X %02X %02X",prov,keytyp,keyid); 00400 } 00401 00402 // -- cSystemCryptoworks ------------------------------------------------------- 00403 00404 #define ECM_ALGO_TYP 5 00405 #define ECM_DATA_START ECM_ALGO_TYP 00406 #define ECM_NANO_LEN 7 00407 #define ECM_NANO_START 8 00408 00409 class cSystemCryptoworks : public cSystem, private cCryptoworks { 00410 private: 00411 public: 00412 cSystemCryptoworks(void); 00413 virtual bool ProcessECM(const cEcmInfo *ecmInfo, unsigned char *data); 00414 // virtual void ProcessEMM(int pid, int caid, unsigned char *data); 00415 }; 00416 00417 cSystemCryptoworks::cSystemCryptoworks(void) 00418 :cSystem(SYSTEM_NAME,SYSTEM_PRI) 00419 { 00420 // hasLogger=true; 00421 } 00422 00423 bool cSystemCryptoworks::ProcessECM(const cEcmInfo *ecmInfo, unsigned char *data) 00424 { 00425 int len=SCT_LEN(data); 00426 if(data[ECM_NANO_LEN]!=len-ECM_NANO_START) { 00427 PRINTF(L_SYS_ECM,"invalid ECM structure"); 00428 return false; 00429 } 00430 00431 int prov=-1, keyid=0; 00432 for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) { 00433 if(data[i]==0x83) { 00434 prov =data[i+2]&0xFC; 00435 keyid=data[i+2]&0x03; 00436 break; 00437 } 00438 } 00439 if(prov<0) { 00440 PRINTF(L_SYS_ECM,"provider ID not located in ECM"); 00441 return false; 00442 } 00443 00444 unsigned char key[22]; 00445 cPlainKey *pk; 00446 if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,CCTYP,CCID),6))) { 00447 if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X CC key",ecmInfo->caId,prov); 00448 return false; 00449 } 00450 pk->Get(key+16); 00451 00452 // RSA stage 00453 DUMPNANO("pre-RSA",&data[ECM_NANO_START],len-ECM_NANO_START); 00454 for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) { 00455 int l=data[i+1]+2; 00456 switch(data[i]) { 00457 case 0x85: 00458 { 00459 if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,0x31,keyid),16))) { 00460 if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X 31 %02X key",ecmInfo->caId,prov,keyid); 00461 return false; 00462 } 00463 pk->Get(key); 00464 cBN mod; 00465 if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,0x10,0x00),64))) { 00466 if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X 10 00 key",ecmInfo->caId,prov); 00467 return false; 00468 } 00469 pk->Get(mod); 00470 00471 l-=10; 00472 if(!DecryptRSA(&data[i+2],l,data[ECM_ALGO_TYP],key,mod)) 00473 return false; 00474 memmove(&data[i],&data[i+2],l); 00475 memmove(&data[i+l],&data[i+l+10],len-i-l); 00476 len-=10; 00477 break; 00478 } 00479 case 0x86: 00480 memmove(&data[i],&data[i+l],len-i-l); 00481 len-=l; 00482 continue; 00483 } 00484 } 00485 DUMPNANO("post-RSA",&data[ECM_NANO_START],len-ECM_NANO_START); 00486 00487 cKeySnoop ks(this,'W',ecmInfo->caId,KEYSET(prov,0x20,keyid)); 00488 if(!(pk=keys.FindKey('W',ecmInfo->caId,KEYSET(prov,0x20,keyid),16))) { 00489 if(doLog) PRINTF(L_SYS_KEY,"missing %04X %02X 20 %02X key",ecmInfo->caId,prov,keyid); 00490 return false; 00491 } 00492 pk->Get(key); 00493 00494 // DES stage 00495 unsigned char sig[8]; 00496 LDUMP(L_SYS_VERBOSE,&data[len-8],8,"sig org:"); 00497 data[ECM_NANO_LEN]=len-ECM_NANO_START; 00498 Signature(&data[ECM_DATA_START],len-ECM_DATA_START-10,key,sig); 00499 for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) { 00500 switch(data[i]) { 00501 case 0xDA: 00502 case 0xDB: 00503 case 0xDC: 00504 for(int j=0; j<data[i+1]; j+=8) 00505 DecryptDES(&data[i+2+j],data[ECM_ALGO_TYP],key); 00506 break; 00507 case 0xDF: 00508 if(memcmp(&data[i+2],sig,8)) { 00509 PRINTF(L_SYS_ECM,"signature failed in ECM"); 00510 return false; 00511 } 00512 break; 00513 } 00514 } 00515 00516 // CW stage 00517 for(int i=ECM_NANO_START; i<len; i+=data[i+1]+2) { 00518 switch(data[i]) { 00519 case 0xDB: 00520 if(data[i+1]==0x10) { 00521 memcpy(cw,&data[i+2],16); 00522 LDUMP(L_SYS_VERBOSE,cw,16,"cw:"); 00523 ks.OK(pk); 00524 return true; 00525 } 00526 break; 00527 } 00528 } 00529 00530 return false; 00531 } 00532 00533 /* 00534 void cSystemCryptoworks::ProcessEMM(int pid, int caid, unsigned char *data) 00535 { 00536 } 00537 */ 00538 00539 // -- cSystemLinkCryptoworks --------------------------------------------------- 00540 00541 class cSystemLinkCryptoworks : public cSystemLink { 00542 public: 00543 cSystemLinkCryptoworks(void); 00544 virtual bool CanHandle(unsigned short SysId); 00545 virtual cSystem *Create(void) { return new cSystemCryptoworks; } 00546 }; 00547 00548 static cSystemLinkCryptoworks staticInit; 00549 00550 cSystemLinkCryptoworks::cSystemLinkCryptoworks(void) 00551 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI) 00552 { 00553 Feature.NeedsKeyFile(); 00554 } 00555 00556 bool cSystemLinkCryptoworks::CanHandle(unsigned short SysId) 00557 { 00558 SysId&=SYSTEM_MASK; 00559 return SYSTEM_CAN_HANDLE(SysId); 00560 }