|
SASC
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 <openssl/sha.h> 00026 00027 #include "system-common.h" 00028 #include "data.h" 00029 #include "helper.h" 00030 #include "crypto.h" 00031 #include "parse.h" 00032 #include "misc.h" 00033 #include "log-sys.h" 00034 #include "log-core.h" 00035 #include "version.h" 00036 00037 SCAPIVERSTAG(); 00038 00039 #define SYSTEM_SECA 0x0100 00040 00041 #define SYSTEM_NAME "Seca" 00042 #define SYSTEM_PRI -10 00043 #define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_SECA) 00044 00045 #define FILEMAP_DOMAIN "seca" 00046 00047 #define L_SYS 14 00048 #define L_SYS_ALL LALL(L_SYS_LASTDEF) 00049 00050 static const struct LogModule lm_sys = { 00051 (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK, 00052 (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK, 00053 "seca", 00054 { L_SYS_DEFNAMES } 00055 }; 00056 ADD_MODULE(L_SYS,lm_sys) 00057 00058 // -- cPlainKeySeca ------------------------------------------------------------ 00059 00060 #define PLAINLEN_SECA_H 8 00061 #define PLAINLEN_SECA_D 16 00062 #define PLAINLEN_SECA_B 90 00063 #define PLAINLEN_SECA_E 6 // exponent key len 00064 #define EMM_MAGIC 1 00065 #define N51_MAGIC 2 00066 00067 class cPlainKeySeca : public cDualKey { 00068 protected: 00069 virtual bool IsBNKey(void) const; 00070 virtual int IdSize(void) { return 4; } 00071 virtual cString PrintKeyNr(void); 00072 public: 00073 cPlainKeySeca(bool Super); 00074 virtual bool Parse(const char *line); 00075 }; 00076 00077 static cPlainKeyTypeReg<cPlainKeySeca,'S'> KeyReg; 00078 00079 cPlainKeySeca::cPlainKeySeca(bool Super) 00080 :cDualKey(Super,true) 00081 {} 00082 00083 bool cPlainKeySeca::IsBNKey(void) const 00084 { 00085 switch(keynr&C2MASK) { 00086 case MBC('E','1'): 00087 case MBC('M','1'): 00088 case MBC('E','3'): 00089 case MBC('M','3'): 00090 case MBC('E','5'): 00091 case MBC('M','5'): 00092 case MBC('E','9'): 00093 case MBC('M','9'): return true; 00094 } 00095 return false; 00096 } 00097 00098 bool cPlainKeySeca::Parse(const char *line) 00099 { 00100 unsigned char sid[2]; 00101 int len; 00102 if(GetChar(line,&type,1) && (len=GetHex(line,sid,2,false))) { 00103 type=toupper(type); id=Bin2Int(sid,len); 00104 line=skipspace(line); 00105 int emmnr=0, keylen=PLAINLEN_SECA_B; 00106 if(!strncasecmp(line,"EMM",3)) { // EMM RSA key 00107 emmnr=EMM_MAGIC; 00108 line+=3; 00109 line=skipspace(line); 00110 } 00111 else if(!strncasecmp(line,"N51",3)) { // Nano 51 RSA key 00112 emmnr=N51_MAGIC; 00113 line+=3; 00114 line=skipspace(line); 00115 keylen=toupper(*line)=='E'?1:129; 00116 } 00117 bool ok; 00118 switch(toupper(*line)) { 00119 case 'E': 00120 case 'M': ok=GetChar(line,&keynr,2); 00121 keynr=ADDC3(keynr,emmnr); 00122 break; 00123 default: ok=emmnr ? false : GetHex(line,sid,1); 00124 keynr=sid[0]; 00125 break; 00126 } 00127 if(ok) { 00128 unsigned char *skey=AUTOMEM(keylen); 00129 len=GetHex(line,skey,keylen,false); 00130 if(IsBNKey()) { 00131 if(C2(keynr)=='E' && len==PLAINLEN_SECA_E) { 00132 // support short exponent keys 00133 keylen=len; 00134 } 00135 } 00136 else { 00137 if(len==PLAINLEN_SECA_H || len==PLAINLEN_SECA_D) { 00138 // support for 16 & 8 byte keys 00139 keylen=len; 00140 } 00141 } 00142 if(len==keylen) { 00143 SetBinKey(skey,keylen); 00144 return true; 00145 } 00146 } 00147 } 00148 return false; 00149 } 00150 00151 cString cPlainKeySeca::PrintKeyNr(void) 00152 { 00153 char nr[32]; 00154 int q=0; 00155 switch(C3(keynr)) { 00156 case EMM_MAGIC: q+=snprintf(nr+q,sizeof(nr)-q,"EMM "); break; 00157 case N51_MAGIC: q+=snprintf(nr+q,sizeof(nr)-q,"N51 "); break; 00158 } 00159 if(IsBNKey()) { 00160 nr[q ]=(keynr>>8) & 0xff; 00161 nr[q+1]= keynr & 0xff; 00162 nr[q+2]=0; 00163 q+=2; 00164 } 00165 else q+=snprintf(nr+q,sizeof(nr)-q,"%.2X",keynr); 00166 return nr; 00167 } 00168 00169 // -- cSecaCardInfo ------------------------------------------------------------ 00170 00171 class cSecaCardInfo : public cStructItem, public cProviderSeca { 00172 private: 00173 int len; 00174 public: 00175 unsigned char key[16]; 00176 // 00177 bool Parse(const char *line); 00178 int KeySize(void) { return len; } 00179 }; 00180 00181 bool cSecaCardInfo::Parse(const char *line) 00182 { 00183 return GetHex(line,provId,sizeof(provId)) && 00184 GetHex(line,sa,sizeof(sa)) && 00185 (len=GetHex(line,key,sizeof(key),false)) && 00186 (len==PLAINLEN_SECA_H || len==PLAINLEN_SECA_D); 00187 } 00188 00189 // -- cSecaCardInfos ----------------------------------------------------------- 00190 00191 class cSecaCardInfos : public cCardInfos<cSecaCardInfo> { 00192 public: 00193 cSecaCardInfos(void):cCardInfos<cSecaCardInfo>("Seca cards","Seca.KID",0) {} 00194 }; 00195 00196 static cSecaCardInfos Scards; 00197 00198 // -- cSeca -------------------------------------------------------------------- 00199 00200 static const unsigned char secaPC1[] = { 00201 42,57,29,34, 41,53,30,15, 00202 19,36,23,14, 43,61,12, 3, 00203 51,49,5, 6, 45,54,52,47, 00204 63,38,58,22, 60,33,10,26, 00205 37,35,44, 1, 20,62,28,18, 00206 46, 9,39, 4, 27,11,21,50, 00207 31,25, 2, 7, 13,55,59,17 00208 }; 00209 00210 static const unsigned char secaPC2[] = { 00211 18, 3,21,15, 42,35,37, 8, 00212 49,41,30,55, 56,29,12,23, 00213 43,14,7 ,27, 13, 2,11,45, 00214 4,34,54,51, 22,40,16,25, 00215 26,48,53,28, 1,17, 5,31, 00216 50, 6,39,24, 33,47,38,32 00217 }; 00218 00219 static inline void __swap8_4(unsigned char *data) 00220 { 00221 unsigned char temp[4]; 00222 memcpy(temp,data,4); 00223 memcpy(data,&data[4],4); 00224 memcpy(&data[4],temp,4); 00225 } 00226 #define swap8_4(d) __swap8_4(d) 00227 00228 class cSeca { 00229 private: 00230 static const unsigned char TD[]; 00231 // 00232 void Fase(unsigned char *data, const unsigned char *key, const unsigned char *T1, const unsigned char *T2); 00233 protected: 00234 static const unsigned char T1_S1[], T2_S1[]; 00235 // 00236 void Decrypt(unsigned char *data, const unsigned char *key, const unsigned char *T1, const unsigned char *T2); 00237 void Encrypt(unsigned char *data, const unsigned char *key, const unsigned char *T1, const unsigned char *T2); 00238 void CalcSignature(const unsigned char *buff, int len, unsigned char *signature, const unsigned char *k, const unsigned char *T1, const unsigned char *T2); 00239 // Seca2 functions 00240 void AdditionalAlgo(unsigned char *data, const unsigned char *key, const int mode); 00241 }; 00242 00243 const unsigned char cSeca::TD[4] = { 1,3,0,2 }; 00244 00245 const unsigned char cSeca::T1_S1[256] = { // Original Tables 00246 0x2a,0xe1,0x0b,0x13,0x3e,0x6e,0x32,0x48, 0xd3,0x31,0x08,0x8c,0x8f,0x95,0xbd,0xd0, 00247 0xe4,0x6d,0x50,0x81,0x20,0x30,0xbb,0x75, 0xf5,0xd4,0x7c,0x87,0x2c,0x4e,0xe8,0xf4, 00248 0xbe,0x24,0x9e,0x4d,0x80,0x37,0xd2,0x5f, 0xdb,0x04,0x7a,0x3f,0x14,0x72,0x67,0x2d, 00249 0xcd,0x15,0xa6,0x4c,0x2e,0x3b,0x0c,0x41, 0x62,0xfa,0xee,0x83,0x1e,0xa2,0x01,0x0e,//8 00250 0x7f,0x59,0xc9,0xb9,0xc4,0x9d,0x9b,0x1b, 0x9c,0xca,0xaf,0x3c,0x73,0x1a,0x65,0xb1, 00251 0x76,0x84,0x39,0x98,0xe9,0x53,0x94,0xba, 0x1d,0x29,0xcf,0xb4,0x0d,0x05,0x7d,0xd1, 00252 0xd7,0x0a,0xa0,0x5c,0x91,0x71,0x92,0x88, 0xab,0x93,0x11,0x8a,0xd6,0x5a,0x77,0xb5, 00253 0xc3,0x19,0xc1,0xc7,0x8e,0xf9,0xec,0x35, 0x4b,0xcc,0xd9,0x4a,0x18,0x23,0x9f,0x52,//16 00254 0xdd,0xe3,0xad,0x7b,0x47,0x97,0x60,0x10, 0x43,0xef,0x07,0xa5,0x49,0xc6,0xb3,0x55, 00255 0x28,0x51,0x5d,0x64,0x66,0xfc,0x44,0x42, 0xbc,0x26,0x09,0x74,0x6f,0xf7,0x6b,0x4f, 00256 0x2f,0xf0,0xea,0xb8,0xae,0xf3,0x63,0x6a, 0x56,0xb2,0x02,0xd8,0x34,0xa4,0x00,0xe6, 00257 0x58,0xeb,0xa3,0x82,0x85,0x45,0xe0,0x89, 0x7e,0xfd,0xf2,0x3a,0x36,0x57,0xff,0x06,//24 00258 0x69,0x54,0x79,0x9a,0xb6,0x6c,0xdc,0x8b, 0xa7,0x1f,0x90,0x03,0x17,0x1c,0xed,0xd5, 00259 0xaa,0x5e,0xfe,0xda,0x78,0xb0,0xbf,0x12, 0xa8,0x22,0x21,0x3d,0xc2,0xc0,0xb7,0xa9, 00260 0xe7,0x33,0xfb,0xf1,0x70,0xe5,0x17,0x96, 0xf8,0x8d,0x46,0xa1,0x86,0xe2,0x40,0x38, 00261 0xf6,0x68,0x25,0x16,0xac,0x61,0x27,0xcb, 0x5b,0xc8,0x2b,0x0f,0x99,0xde,0xce,0xc5 00262 }; 00263 00264 const unsigned char cSeca::T2_S1[256] = { 00265 0xbf,0x11,0x6d,0xfa,0x26,0x7f,0xf3,0xc8, 0x9e,0xdd,0x3f,0x16,0x97,0xbd,0x08,0x80, 00266 0x51,0x42,0x93,0x49,0x5b,0x64,0x9b,0x25, 0xf5,0x0f,0x24,0x34,0x44,0xb8,0xee,0x2e, 00267 0xda,0x8f,0x31,0xcc,0xc0,0x5e,0x8a,0x61, 0xa1,0x63,0xc7,0xb2,0x58,0x09,0x4d,0x46, 00268 0x81,0x82,0x68,0x4b,0xf6,0xbc,0x9d,0x03, 0xac,0x91,0xe8,0x3d,0x94,0x37,0xa0,0xbb, //8 00269 0xce,0xeb,0x98,0xd8,0x38,0x56,0xe9,0x6b, 0x28,0xfd,0x84,0xc6,0xcd,0x5f,0x6e,0xb6, 00270 0x32,0xf7,0x0e,0xf1,0xf8,0x54,0xc1,0x53, 0xf0,0xa7,0x95,0x7b,0x19,0x21,0x23,0x7d, 00271 0xe1,0xa9,0x75,0x3e,0xd6,0xed,0x8e,0x6f, 0xdb,0xb7,0x07,0x41,0x05,0x77,0xb4,0x2d, 00272 0x45,0xdf,0x29,0x22,0x43,0x89,0x83,0xfc, 0xd5,0xa4,0x88,0xd1,0xf4,0x55,0x4f,0x78,//16 00273 0x62,0x1e,0x1d,0xb9,0xe0,0x2f,0x01,0x13, 0x15,0xe6,0x17,0x6a,0x8d,0x0c,0x96,0x7e, 00274 0x86,0x27,0xa6,0x0d,0xb5,0x73,0x71,0xaa, 0x36,0xd0,0x06,0x66,0xdc,0xb1,0x2a,0x5a, 00275 0x72,0xbe,0x3a,0xc5,0x40,0x65,0x1b,0x02, 0x10,0x9f,0x3b,0xf9,0x2b,0x18,0x5c,0xd7, 00276 0x12,0x47,0xef,0x1a,0x87,0xd2,0xc2,0x8b, 0x99,0x9c,0xd3,0x57,0xe4,0x76,0x67,0xca,//24 00277 0x3c,0xfb,0x90,0x20,0x14,0x48,0xc9,0x60, 0xb0,0x70,0x4e,0xa2,0xad,0x35,0xea,0xc4, 00278 0x74,0xcb,0x39,0xde,0xe7,0xd4,0xa3,0xa5, 0x04,0x92,0x8c,0xd9,0x7c,0x1c,0x7a,0xa8, 00279 0x52,0x79,0xf2,0x33,0xba,0x1f,0x30,0x9a, 0x00,0x50,0x4c,0xff,0xe5,0xcf,0x59,0xc3, 00280 0xe3,0x0a,0x85,0xb3,0xae,0xec,0x0b,0xfe, 0xe2,0xab,0x4a,0xaf,0x69,0x6c,0x2c,0x5d 00281 }; 00282 00283 void cSeca::Fase(unsigned char *D, const unsigned char *key, const unsigned char *T1, const unsigned char *T2) 00284 { 00285 for(int l=0; l<4; ++l) { D[l]^=key[l]; D[l]=T1[D[l]&0xff]; } 00286 for(int l=6; l>3; --l) { 00287 D[(l+2)&3]^=D[(l+1)&3]; 00288 D[l&3]=T2[(sn8(D[(l+1)&3])+D[l&3])&0xff]; 00289 } 00290 for(int l=3; l>0; --l) { 00291 D[(l+2)&3]^=D[(l+1)&3]; 00292 D[l&3]=T1[(sn8(D[(l+1)&3])+D[l&3])&0xff]; 00293 } 00294 D[2]^=D[1]; 00295 D[1]^=D[0]; 00296 } 00297 00298 void cSeca::Decrypt(unsigned char *d, const unsigned char *key, const unsigned char *T1, const unsigned char *T2) 00299 { 00300 unsigned char k[16],D[4]; 00301 memcpy(k,key,sizeof(k)); 00302 unsigned char C=0xff; 00303 for(int j=0; j<4; ++j) { 00304 for(int i=0; i<16; ++i) { 00305 if((i&3)==0) ++C; 00306 k[i]^=T1[(k[(15+i)&0xf]^k[(i+1)&0xf]^C)&0xff]; 00307 } 00308 } 00309 int j=0; 00310 for(int i=0; i<16; ++i) { 00311 for(int l=0; l<4; ++l) D[l]=d[l+4]; 00312 j=(j+12)&0xf; 00313 Fase(D,&k[j&0xc],T1,T2); 00314 for(int l=0; l<4; ++l) d[l]^=T2[D[TD[l]]&0xff]; 00315 for(int l=3; l>=0; --l) k[(j+l)&0xf]^=T1[(k[(j+l+1)&0xf]^k[(j+l+15)&0xf]^(15-i))&0xff]; 00316 if(i<15) swap8_4(d); 00317 } 00318 } 00319 00320 void cSeca::Encrypt(unsigned char *d, const unsigned char *key, const unsigned char *T1, const unsigned char *T2) 00321 { 00322 unsigned char D[4],kk[16]; 00323 memcpy(kk, key, sizeof(kk)); 00324 for(int j=0, i=0; i<16; ++i, j=(j+4)&0xf) { 00325 for(int l=0; l<4; ++l) kk[(j+l)&0xf] ^= T1[(kk[(j+l+1)&0xf]^kk[(j+l+15)&0xf]^i)&0xff]; 00326 if(i>0) swap8_4(d); 00327 for(int l=0; l<4; ++l) D[l]=d[l+4]; 00328 Fase(D,&kk[j&0xc],T1,T2); 00329 for(int l=0; l<4; ++l) d[l]^=T2[D[TD[l]]&0xff]; 00330 } 00331 } 00332 00333 void cSeca::CalcSignature(const unsigned char *buff, int len, unsigned char *signature, const unsigned char *k, const unsigned char *T1, const unsigned char *T2) 00334 { 00335 memset(signature,0,8); 00336 for(int i=0 ; i<len ; i+=8) { 00337 for(int j=0 ; j<8 && i+j<len; j++) signature[j]^=buff[i+j]; 00338 Encrypt(signature,k,T1,T2); 00339 } 00340 } 00341 00342 void cSeca::AdditionalAlgo(unsigned char *data, const unsigned char *key, const int mode) 00343 { 00344 static const unsigned int adders[] = { 00345 0x0000,0xe555,0xafff,0x5ffe,0xf552,0x6ffb,0xcff9,0x154c, 00346 0x3ff4,0x4ff1,0x4543,0x1fea,0xdfe6,0x8537,0x0fdd,0x7fd8 00347 }; 00348 const unsigned short * const k = (const unsigned short *)key; 00349 unsigned short * const dd = (unsigned short *)data; 00350 unsigned int d1=dd[0], d2=dd[1], d3=dd[2], d4=dd[3]; 00351 PRINTF(L_SYS_VERBOSE,"additional algo: %s",!mode?"encrypt":"decrypt"); 00352 if(!mode) { 00353 for(int i=0; i<0x10; i++) { 00354 const unsigned int adder = adders[i]; 00355 d1 += (k[0] + d3 + adder) ^ (k[1] + d4 + adder); 00356 d2 += (k[2] + d3 + adder) ^ (k[3] + d4 + adder); 00357 d1 = ror16(d1,5); 00358 d2 = rol16(d2,3); 00359 d3 += (k[0] + d1 + adder) ^ (k[1] + d2 + adder); 00360 d4 += (k[2] + d1 + adder) ^ (k[3] + d2 + adder); 00361 d3 = rol16(d3,3); 00362 d4 = ror16(d4,5); 00363 } 00364 } 00365 else { 00366 for(int i=0xf; i>=0; i--) { 00367 const unsigned int adder = adders[i]; 00368 d4 = rol16(d4,5); 00369 d3 = ror16(d3,3); 00370 d4 -= (k[2] + d1 + adder) ^ (k[3] + d2 + adder); 00371 d3 -= (k[0] + d1 + adder) ^ (k[1] + d2 + adder); 00372 d2 = ror16(d2,3); 00373 d1 = rol16(d1,5); 00374 d2 -= (k[2] + d3 + adder) ^ (k[3] + d4 + adder); 00375 d1 -= (k[0] + d3 + adder) ^ (k[1] + d4 + adder); 00376 } 00377 } 00378 dd[0]=d1; dd[1]=d2; dd[2]=d3; dd[3]=d4; 00379 } 00380 00381 // -- cSeca2Prov --------------------------------------------------------------- 00382 00383 #define MAX_PERMS 10 00384 #define KEY2INDEX(x) (((x)>>5)&0x03) 00385 00386 struct Perm { 00387 unsigned char P1[8], P2[8], P3[8], P4[8]; 00388 }; 00389 00390 struct ProvData { 00391 unsigned short LoadId, MTLoadSize, MTSize; 00392 unsigned char SHA1Pad, SHA1End; 00393 unsigned char FP[8]; 00394 }; 00395 00396 class cSeca2Prov: protected cSeca { 00397 private: 00398 cFileMap *hash, *mask; 00399 unsigned short id; 00400 // 00401 unsigned short Sum(const unsigned char *data, int n) const; 00402 protected: 00403 const struct ProvData *pData; 00404 const struct Perm *perm; 00405 // 00406 cFileMap *GetMap(const char *type, int size, bool generic) const; 00407 public: 00408 cSeca2Prov(unsigned short Id); 00409 virtual ~cSeca2Prov(); 00410 // provider specific mods 00411 virtual void PreSSE(unsigned char *data, int pos) {} 00412 virtual void PostSSE(unsigned char *data, int pos) {} 00413 virtual void SignatureMod(unsigned char *MD, const unsigned char *PK) {} 00414 virtual void PreCW(unsigned char *data) {} 00415 virtual void PostCW(unsigned char *data) {} 00416 virtual void ChainTableXor(unsigned char *data, unsigned short index)=0; 00417 virtual bool DoSigCheck(void) { return true; } 00418 // 00419 virtual bool Init(void); 00420 void CalcSHASignature(const unsigned char *data, int n, unsigned char *signature, bool PadMode=true); 00421 bool DecryptSE(unsigned char *data, const unsigned char *key, int n, int start, const unsigned char *T1, const unsigned char *T2); 00422 bool Matches(unsigned short Id) const { return Id==id; } 00423 // 00424 const unsigned char *T1(int index) const; 00425 const unsigned char *T2(int index) const; 00426 const struct Perm *P(int index) const; 00427 inline const unsigned char *MT(void) const { return mask->Addr(); } 00428 inline int MTSize(void) const { return pData->MTSize; } 00429 inline const unsigned char *FP(void) const { return pData->FP; } 00430 }; 00431 00432 cSeca2Prov::cSeca2Prov(unsigned short Id) 00433 { 00434 id=Id; 00435 pData=0; perm=0; hash=0; mask=0; 00436 } 00437 00438 cSeca2Prov::~cSeca2Prov() 00439 { 00440 if(hash) hash->Unmap(); 00441 if(mask) mask->Unmap(); 00442 } 00443 00444 bool cSeca2Prov::Init(void) 00445 { 00446 hash=GetMap("hash",1536,false); 00447 mask=GetMap("mt",pData->MTLoadSize,false); 00448 if(!hash || !mask) return false; 00449 return true; 00450 } 00451 00452 cFileMap *cSeca2Prov::GetMap(const char *type, int size, bool generic) const 00453 { 00454 char name[32]; 00455 snprintf(name,sizeof(name),generic ? "s2_%s.bin" : "s2_%s_%04x.bin",type,pData->LoadId); 00456 cFileMap *map=filemaps.GetFileMap(name,FILEMAP_DOMAIN,false); 00457 if(!map) 00458 PRINTF(L_SYS_CRYPTO,"no filemap for %s",name); 00459 else if(!map->Map()) { 00460 PRINTF(L_SYS_CRYPTO,"mapping failed for %s",name); 00461 map=0; 00462 } 00463 else if(map->Size()<size) { 00464 PRINTF(L_SYS_CRYPTO,"%s file %s has wrong size (has=%d wanted=%d)",type,name,map->Size(),size); 00465 map->Unmap(); 00466 map=0; 00467 } 00468 return map; 00469 } 00470 00471 // Hash file layout is (Yankse style): 00472 // Table T1 for 9x, 00473 // Table T1 for Bx, 00474 // Table T1 for FX, 00475 // Table T2 for 9x, 00476 // Table T2 for Bx, 00477 // Table T2 for FX (total: 1536 bytes) 00478 00479 const unsigned char *cSeca2Prov::T1(int index) const 00480 { 00481 static int idxTrans[] = { 0,1,2,2 }; 00482 if(index>=0 && index<=3) { 00483 return hash->Addr()+(idxTrans[index]*256); 00484 } 00485 PRINTF(L_SYS_CRYPTO,"bad T1 table index %d",index); 00486 return 0; 00487 } 00488 00489 const unsigned char *cSeca2Prov::T2(int index) const 00490 { 00491 static int idxTrans[] = { 0,1,2,2 }; 00492 if(index>=0 && index<=3) { 00493 return hash->Addr()+(idxTrans[index]*256)+768; 00494 } 00495 PRINTF(L_SYS_CRYPTO,"bad T2 table index %d",index); 00496 return 0; 00497 } 00498 00499 const struct Perm *cSeca2Prov::P(int index) const 00500 { 00501 if(index>=0 && index<MAX_PERMS && perm) { 00502 return &perm[index]; 00503 } 00504 PRINTF(L_SYS_CRYPTO,"no perm table or bad index %d",index); 00505 return 0; 00506 } 00507 00508 unsigned short cSeca2Prov::Sum(const unsigned char *data, int n) const 00509 { 00510 unsigned int sum=0; 00511 for(int i=1; i<n; i+=2) sum+=((data[i-1]<<8)+data[i]); 00512 if(n&1) sum+=(data[n-1]<<4); 00513 return sum&0x3FFF; 00514 } 00515 00516 bool cSeca2Prov::DecryptSE(unsigned char *data, const unsigned char *key, int n, int start, const unsigned char *T1, const unsigned char *T2) 00517 { 00518 const int sigStart=n-data[n-1]-9; // 82 <8 bytes> P5(sigStart) 00519 const int encrLen=sigStart-16; 00520 00521 #ifdef DEBUG_SECA_EXTRA 00522 if(encrLen>=n || encrLen<0) printf("encrLen error in SE\n"); 00523 if(sigStart<16) printf("sigStart error in SE\n"); 00524 #endif 00525 if(encrLen>=n || encrLen<0 || sigStart<16) return false; 00526 00527 Decrypt(data+sigStart-8,key,T1,T2); 00528 ChainTableXor(data+sigStart-8,Sum(data+start,sigStart-8-start)); 00529 int i; 00530 00531 for(i=start; i<encrLen; i+=8) { 00532 Decrypt(data+i,key,T1,T2); 00533 ChainTableXor(data+i,Sum(&data[i+8],8)); 00534 } 00535 00536 int restBytes=sigStart&0x07; 00537 if(!restBytes) restBytes=8; 00538 00539 // Last Block 00540 unsigned char lastBlock[8]; 00541 memset(lastBlock,0,sizeof(lastBlock)); 00542 memcpy(lastBlock,data+sigStart-restBytes,restBytes); 00543 Decrypt(lastBlock,key,T1,T2); 00544 00545 Decrypt(data+i,key,T1,T2); 00546 ChainTableXor(data+i,Sum(lastBlock,sizeof(lastBlock))); 00547 return true; 00548 } 00549 00550 void cSeca2Prov::CalcSHASignature(const unsigned char *data, int n, unsigned char *signature, bool PadMode) 00551 { 00552 SHA_CTX ctx; 00553 SHA1_Init(&ctx); 00554 SHA1_Update(&ctx,data,n); 00555 unsigned char Pad=0; 00556 if(PadMode) { 00557 unsigned char End=pData->SHA1End; 00558 SHA1_Update(&ctx,&End,1); 00559 int l=(n&63)+1; 00560 Pad=pData->SHA1Pad; 00561 if(l>62) { 00562 for(; l<64; l++) SHA1_Update(&ctx,&Pad,1); 00563 l=0; 00564 } 00565 for(; l<62; l++) SHA1_Update(&ctx,&Pad,1); 00566 unsigned short s=bswap_16(n); 00567 SHA1_Update(&ctx,&s,2); 00568 } 00569 else for(; n&63; n++) SHA1_Update(&ctx,&Pad,1); 00570 00571 *((unsigned int *)(signature ))=bswap_32(ctx.h0); 00572 *((unsigned int *)(signature+ 4))=bswap_32(ctx.h1); 00573 *((unsigned int *)(signature+ 8))=bswap_32(ctx.h2); 00574 *((unsigned int *)(signature+12))=bswap_32(ctx.h3); 00575 *((unsigned int *)(signature+16))=bswap_32(ctx.h4); 00576 } 00577 00578 // -- cSecaProviders & cSecaProviderLink --------------------------------------- 00579 00580 class cSeca2ProvLink { 00581 friend class cSeca2Providers; 00582 private: 00583 cSeca2ProvLink *next; 00584 const unsigned short *ids; 00585 public: 00586 cSeca2ProvLink(const unsigned short *Ids); 00587 bool CanHandle(unsigned short Id); 00588 virtual cSeca2Prov *Create(unsigned short Id)=0; 00589 virtual ~cSeca2ProvLink() {}; 00590 }; 00591 00592 template<class CC> class cSeca2ProvLinkReg : public cSeca2ProvLink { 00593 public: 00594 cSeca2ProvLinkReg(const unsigned short *Ids):cSeca2ProvLink(Ids) {} 00595 virtual cSeca2Prov *Create(unsigned short Id) { return new CC(Id); } 00596 }; 00597 00598 class cSeca2Providers { 00599 friend class cSeca2ProvLink; 00600 private: 00601 static cSeca2ProvLink *first; 00602 // 00603 static void Register(cSeca2ProvLink *spl); 00604 public: 00605 static cSeca2Prov *GetProv(unsigned short id); 00606 }; 00607 00608 cSeca2ProvLink *cSeca2Providers::first=0; 00609 00610 void cSeca2Providers::Register(cSeca2ProvLink *spl) 00611 { 00612 LBSTART(L_CORE_DYN); 00613 LBPUT("seca2prov: registering Seca2 provider"); 00614 for(int i=0; spl->ids[i]; i++) LBPUT(" %.4x",spl->ids[i]); 00615 LBEND(); 00616 spl->next=first; 00617 first=spl; 00618 } 00619 00620 cSeca2Prov *cSeca2Providers::GetProv(unsigned short id) 00621 { 00622 cSeca2ProvLink *spl=first; 00623 while(spl) { 00624 if(spl->CanHandle(id)) { 00625 cSeca2Prov *sp=spl->Create(id); 00626 if(sp && sp->Init()) return sp; 00627 delete sp; 00628 } 00629 spl=spl->next; 00630 } 00631 return 0; 00632 } 00633 00634 cSeca2ProvLink::cSeca2ProvLink(const unsigned short *Ids) 00635 { 00636 ids=Ids; 00637 cSeca2Providers::Register(this); 00638 } 00639 00640 bool cSeca2ProvLink::CanHandle(unsigned short Id) 00641 { 00642 for(int i=0; ids[i]; i++) if(ids[i]==Id) return true; 00643 return false; 00644 } 00645 00646 // -- cSeca2ProvSSE ------------------------------------------------------------ 00647 00648 #define beforeSig (pos-8) 00649 #define afterSig (pos+1) 00650 00651 class cSeca2ProvSSE : public cSeca2Prov { 00652 private: 00653 virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i)=0; 00654 virtual void PostSSECore1(unsigned char *data, int pos)=0; 00655 virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos)=0; 00656 virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos)=0; 00657 virtual void PostSSECore4(unsigned char *data, int pos)=0; 00658 protected: 00659 cDes des; 00660 cFileMap *sse, *sseP, *cw; 00661 // 00662 virtual bool InitSSE(void)=0; 00663 virtual void PreSSE(unsigned char *data, int pos); 00664 virtual void PostSSE(unsigned char *data, int pos); 00665 // 00666 inline const unsigned char *SSET1(void) const { return sse->Addr(); } 00667 inline const unsigned char *SSET2(void) const { return sse->Addr()+3072; } 00668 inline const unsigned char *SSEPT1(void) const { return sseP->Addr(); } 00669 inline const unsigned char *SSEPT2(void) const { return sseP->Addr()+80; } 00670 inline const unsigned char *CWT1(void) const { return cw->Addr(); } 00671 public: 00672 cSeca2ProvSSE(unsigned short Id); 00673 virtual ~cSeca2ProvSSE(); 00674 virtual bool Init(void); 00675 }; 00676 00677 cSeca2ProvSSE::cSeca2ProvSSE(unsigned short Id) 00678 :cSeca2Prov(Id) 00679 ,des(secaPC1,secaPC2) 00680 { 00681 sse=0; sseP=0; cw=0; 00682 } 00683 00684 cSeca2ProvSSE::~cSeca2ProvSSE() 00685 { 00686 if(sse) sse->Unmap(); 00687 if(sseP) sseP->Unmap(); 00688 if(cw) cw->Unmap(); 00689 } 00690 00691 bool cSeca2ProvSSE::Init(void) 00692 { 00693 return InitSSE() && cSeca2Prov::Init(); 00694 } 00695 00696 void cSeca2ProvSSE::PreSSE(unsigned char *data, int pos) 00697 { 00698 const unsigned char *T1=SSEPT1(); 00699 unsigned char tmpBuf[80]; 00700 00701 data+=pos+5; // Start at offset 5 00702 for(int i=4; i>=0; i--) { 00703 int j=i*16; 00704 PreSSECore(&tmpBuf[j],&data[j],i); 00705 } 00706 for(int i=79; i>=0; i--) data[i]=tmpBuf[i]^T1[i]; 00707 } 00708 00709 void cSeca2ProvSSE::PostSSE(unsigned char *data, int pos) 00710 { 00711 PostSSECore1(data,pos); 00712 // create the SHA hash buffer 00713 unsigned char tmpBuf[64]; 00714 memcpy(tmpBuf+0,&data[beforeSig+0],4); 00715 memcpy(tmpBuf+4,&data[afterSig +4],4); 00716 PostSSECore2(tmpBuf+8,data,pos); 00717 // Calc Signature of the generated buffer here 00718 unsigned char MD[20]; 00719 CalcSHASignature(tmpBuf,sizeof(tmpBuf),MD,false); 00720 // Prepare DES data 00721 memcpy(tmpBuf+0,&data[beforeSig+4],4); 00722 memcpy(tmpBuf+4,&data[afterSig +0],4); 00723 // DES Enrypt 00724 des.Des(tmpBuf,MD,SECA_DES_ENCR); 00725 // modify data with encrypted DES data 00726 PostSSECore3(data,tmpBuf,pos); 00727 // save the signature 00728 memcpy(tmpBuf,data+afterSig,8); 00729 PostSSECore4(data,pos); 00730 // put the signature in the data 00731 memcpy(data+beforeSig,tmpBuf,8); 00732 } 00733 00734 // -- France ------------------------------------------------------------------- 00735 00736 class cSeca2ProvFR : public cSeca2ProvSSE { 00737 private: 00738 virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i); 00739 virtual void PostSSECore1(unsigned char *data, int pos); 00740 virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos); 00741 virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos); 00742 virtual void PostSSECore4(unsigned char *data, int pos); 00743 protected: 00744 virtual bool InitSSE(void); 00745 virtual void PostCW(unsigned char *data); 00746 virtual void ChainTableXor(unsigned char *data, unsigned short index); 00747 virtual void SignatureMod(unsigned char *MD, const unsigned char *PK); 00748 public: 00749 cSeca2ProvFR(unsigned short Id); 00750 }; 00751 00752 static const unsigned short IdsFR[] = { 0x80,0x81,0 }; 00753 00754 static cSeca2ProvLinkReg<cSeca2ProvFR> staticLinkFR(IdsFR); 00755 00756 static const struct ProvData provDataFR = { 00757 0x80,16895,16895,0x7F,0xF7, { 3, 0, 0, 0, 2, 4, 3, 0 } 00758 }; 00759 00760 cSeca2ProvFR::cSeca2ProvFR(unsigned short Id) 00761 :cSeca2ProvSSE(Id) 00762 { 00763 pData=&provDataFR; 00764 } 00765 00766 bool cSeca2ProvFR::InitSSE(void) 00767 { 00768 sse=GetMap("sse",5120,true); 00769 sseP=GetMap("sse",1104,false); 00770 cw=GetMap("cw",512,false); 00771 return sse && sseP && cw; 00772 } 00773 00774 void cSeca2ProvFR::PreSSECore(unsigned char *buf, const unsigned char *data, int i) 00775 { 00776 const unsigned char *T1=SSET1(), *T2=SSET2(); 00777 00778 buf[ 0]=data[0x06]^T2[i+0x0a]; 00779 buf[ 1]=data[0x01]^T2[i+0x00]; 00780 buf[ 2]=data[0x02]^T1[i+0x00]; 00781 buf[ 3]=data[0x03]^T2[i+0x04]; 00782 buf[ 4]=~data[0x04]; 00783 buf[ 5]=data[0x05]^T1[i+0x01]; 00784 buf[ 6]=data[0x00]^T2[i+0x0f]; 00785 buf[ 7]=data[0x07]^T1[i+0x02]; 00786 buf[ 8]=data[0x08]^T1[i+0x00]; 00787 buf[ 9]=data[0x0d]^T2[i+0x14]; 00788 buf[10]=data[0x0f]^T2[i+0x07]; 00789 buf[11]=~data[0x0b]; 00790 buf[12]=data[0x0c]^T1[i+0x00]; 00791 buf[13]=data[0x09]^T2[i+0x19]; 00792 buf[14]=data[0x0e]^T2[i+0x1e]; 00793 buf[15]=data[0x0a]^T1[i+0x01]; 00794 } 00795 00796 void cSeca2ProvFR::PostSSECore1(unsigned char *data, int pos) 00797 { 00798 data[beforeSig+0]^=-(0x2d); 00799 data[beforeSig+1]-=0x22; 00800 data[beforeSig+2]^=0x1d; 00801 data[beforeSig+3]^=-(0x68); 00802 data[beforeSig+4] =~data[beforeSig + 4]; 00803 data[beforeSig+5]^=0x26; 00804 data[beforeSig+6]^=0x09; 00805 data[beforeSig+7]-=0x3e; 00806 data[afterSig +0]^=-(0x5d); 00807 data[afterSig +1]-=0x74; 00808 data[afterSig +2]^=0x2d; 00809 data[afterSig +3]^=-(0x2a); 00810 data[afterSig +4]+=0x0d; 00811 data[afterSig +5]^=-(0x6c); 00812 data[afterSig +6]^=-(0x76); 00813 data[afterSig +7]+=0x31; 00814 } 00815 00816 void cSeca2ProvFR::PostSSECore2(unsigned char *buf, const unsigned char *data, int pos) 00817 { 00818 const unsigned char *T1=SSEPT2(); 00819 memcpy(buf, &T1[data[afterSig+4]+0x48], 56); 00820 } 00821 00822 void cSeca2ProvFR::PostSSECore3(unsigned char *data, const unsigned char *buf, int pos) 00823 { 00824 data[beforeSig+4]=buf[5]; 00825 data[beforeSig+5]=buf[4]; 00826 data[beforeSig+6]=buf[7]; 00827 data[beforeSig+7]=buf[2]; 00828 data[afterSig +0]=buf[3]; 00829 data[afterSig +1]=buf[1]; 00830 data[afterSig +2]=buf[0]; 00831 data[afterSig +3]=buf[6]; 00832 } 00833 00834 void cSeca2ProvFR::PostSSECore4(unsigned char *data, int pos) 00835 { 00836 data[afterSig+0]=data[beforeSig+3]^0x3e; 00837 data[afterSig+1]=data[beforeSig+1]^0x5e; 00838 data[afterSig+2]=data[beforeSig+5]^0x2f; 00839 data[afterSig+3]=data[beforeSig+0]^0x77; 00840 data[afterSig+4]=data[beforeSig+6]^-(0x4b); 00841 data[afterSig+5]=data[beforeSig+2]^-(0x38); 00842 data[afterSig+6]=data[beforeSig+7]^0x29; 00843 data[afterSig+7]=data[beforeSig+4]^0x2b; 00844 } 00845 00846 void cSeca2ProvFR::PostCW(unsigned char *data) 00847 { 00848 const unsigned char *T1=SSET1(), *T2=SSET2(), *T3=SSEPT2(), *T4=CWT1(); 00849 unsigned int idx; 00850 unsigned char key[8]; 00851 idx=((data[0]<<8)|data[1]); key[0]=T3[idx & 0x3FF]; 00852 idx=(idx + key[0]); key[1]=T3[idx & 0x3FF]; 00853 idx=((data[2]<<8)|data[3]); key[2]=T4[idx & 0x1FF]; 00854 idx=idx + key[2]; key[3]=T4[idx & 0x1FF]; 00855 idx=((data[8+4]<<8)|data[8+5]); key[4]=T2[idx & 0x7FF]; 00856 idx=idx + key[4]; key[5]=T2[idx & 0x7FF]; 00857 idx=((data[8+6]<<8)|data[8+7]); key[6]=T1[idx & 0xBFF]; 00858 idx=idx + key[6]; key[7]=T1[idx & 0xBFF]; 00859 des.Des(data+4,key,SECA_DES_ENCR); 00860 } 00861 00862 void cSeca2ProvFR::ChainTableXor(unsigned char *data, unsigned short index) 00863 { 00864 static const unsigned char tabIdx[] = { 0x00, 0x08, 0x03, 0x1F, 0x06, 0x32, 0x12, 0x0C }; 00865 static const unsigned char tabXor[] = { 0x77, 0x2B, 0xC8, 0xEE, 0x2F, 0xD3, 0x22, 0x29 }; 00866 static const unsigned char tabPos[] = { 0, 2, 1, 6, 4, 5, 7, 3 }; 00867 00868 unsigned int idx1, idx2; 00869 unsigned char xorVal=0; 00870 const unsigned char *T1=MT(), *T2=SSET1(); 00871 00872 idx1 = (index^0x17AC) & 0x3FFF; 00873 idx2 = idx1 & 0xBFF; 00874 for(int i=0; i<8; i++) { 00875 idx1 = (idx1 + tabIdx[i]) & 0x3FFF; 00876 idx2 = (idx2 + xorVal) & 0xBFF; 00877 xorVal ^= T1[idx1] ^ tabXor[i]; 00878 data[tabPos[i]] ^= xorVal ^ T2[idx2]; 00879 } 00880 } 00881 00882 void cSeca2ProvFR::SignatureMod(unsigned char *MD, const unsigned char *PK) 00883 { 00884 const unsigned char *T1=SSEPT2(); 00885 unsigned int idx; 00886 00887 idx = ((MD[18] << 8) | MD[19]) & 0x3FF; 00888 MD[10] = T1[idx]; 00889 MD[13] ^= PK[6]; 00890 idx = ((MD[15] << 8) | MD[13]) & 0x3FF; 00891 MD[16] = T1[idx]; 00892 des.Des(MD,MD+10,SECA_DES_ENCR); 00893 } 00894 00895 // -- Netherlands -------------------------------------------------------------- 00896 00897 class cSeca2ProvNL : public cSeca2ProvSSE { 00898 private: 00899 virtual void PreSSECore(unsigned char *buf, const unsigned char *data, int i); 00900 virtual void PostSSECore1(unsigned char *data, int pos); 00901 virtual void PostSSECore2(unsigned char *buf, const unsigned char *data, int pos); 00902 virtual void PostSSECore3(unsigned char *data, const unsigned char *buf, int pos); 00903 virtual void PostSSECore4(unsigned char *data, int pos); 00904 protected: 00905 virtual bool InitSSE(void); 00906 virtual void PostCW(unsigned char *data); 00907 virtual void ChainTableXor(unsigned char *data, unsigned short index); 00908 virtual bool DoSigCheck(void) { return false; } 00909 public: 00910 cSeca2ProvNL(unsigned short Id); 00911 }; 00912 00913 static const unsigned short IdsNL[] = { 0x6a,0 }; 00914 00915 static cSeca2ProvLinkReg<cSeca2ProvNL> staticLinkNL(IdsNL); 00916 00917 static const struct ProvData provDataNL = { 00918 0x6a,16895,16895,0xa3,0x3a, { 3, 0, 0, 0, 2, 4, 3, 0 } 00919 }; 00920 00921 cSeca2ProvNL::cSeca2ProvNL(unsigned short Id) 00922 :cSeca2ProvSSE(Id) 00923 { 00924 pData=&provDataNL; 00925 } 00926 00927 bool cSeca2ProvNL::InitSSE(void) 00928 { 00929 sse=GetMap("sse",5120,true); 00930 sseP=GetMap("sse",336,false); 00931 cw=GetMap("cw",512,false); 00932 return sse && sseP && cw; 00933 } 00934 00935 void cSeca2ProvNL::PreSSECore(unsigned char *buf, const unsigned char *data, int i) 00936 { 00937 const unsigned char *T1=SSET1(), *T2=SSET2(); 00938 00939 buf[0] =data[7] ^T1[i+0x17]; 00940 buf[1] =data[1] ^T2[i+0x07]; 00941 buf[2] =data[2] ^T1[i+0x03]; 00942 buf[3] =data[3] ^T2[i+0x0C]; 00943 buf[4] =~data[4]; 00944 buf[5] =data[5] ^T1[i+0x1E]; 00945 buf[6] =data[6] ^T1[i+0x11]; 00946 buf[7] =data[0] ^T2[i+0x0F]; 00947 buf[8] =data[9] ^T1[i+0x15]; 00948 buf[9] =data[8] ^T2[i+0x04]; 00949 buf[10]=data[12]^T2[i+0x07]; 00950 buf[11]=data[11]^T1[i+0x16]; 00951 buf[12]=data[10]^T1[i+0x01]; 00952 buf[13]=data[13]^T1[i+0x0F]; 00953 buf[14]=~data[14]; 00954 buf[15]=data[15]^T2[i+0x0B]; 00955 } 00956 00957 void cSeca2ProvNL::PostSSECore1(unsigned char *data, int pos) 00958 { 00959 // modify 8 bytes before signature byte (0x82) 00960 data[beforeSig+0] ^= 0xd6; data[beforeSig+1] ^= 0x96; 00961 data[beforeSig+2] -= 0x51; data[beforeSig+3] ^= 0x3a; 00962 data[beforeSig+4] -= 0x8d; data[beforeSig+5] ^= 0xf1; 00963 data[beforeSig+6] -= 0xc2; data[beforeSig+7] ^= 0xb1; 00964 00965 data[afterSig+0] ^= 0x84; data[afterSig+1] ^= 0xf8; 00966 data[afterSig+2] -= 0x7d; data[afterSig+3] = ~(data[afterSig+3]); 00967 data[afterSig+4] ^= 0xfd; data[afterSig+5] ^= 0xd0; 00968 data[afterSig+6] ^= 0x77; data[afterSig+7] ^= 0x25; 00969 } 00970 00971 void cSeca2ProvNL::PostSSECore2(unsigned char *buf, const unsigned char *data, int pos) 00972 { 00973 const unsigned char *T1=SSEPT2(); 00974 memcpy(buf,&T1[(data[afterSig+6]+0x19)&0x7F],56); 00975 } 00976 00977 void cSeca2ProvNL::PostSSECore3(unsigned char *data, const unsigned char *buf, int pos) 00978 { 00979 data[beforeSig+4]=buf[7]; 00980 data[beforeSig+5]=buf[0]; 00981 data[beforeSig+6]=buf[3]; 00982 data[beforeSig+7]=buf[5]; 00983 data[afterSig+0]=buf[6]; 00984 data[afterSig+1]=buf[2]; 00985 data[afterSig+2]=buf[1]; 00986 data[afterSig+3]=buf[4]; 00987 } 00988 00989 void cSeca2ProvNL::PostSSECore4(unsigned char *data, int pos) 00990 { 00991 data[afterSig+0]=data[beforeSig+1] ^ 0x65; data[afterSig+1]=data[beforeSig+0] ^ 0x75; 00992 data[afterSig+2]=data[beforeSig+5] ^ 0x35; data[afterSig+3]=data[beforeSig+3] ^ 0xd9; 00993 data[afterSig+4]=data[beforeSig+6] ^ 0xb7; data[afterSig+5]=data[beforeSig+7] ^ 0x9a; 00994 data[afterSig+6]=data[beforeSig+4] ^ 0xc7; data[afterSig+7]=data[beforeSig+2] ^ 0x1f; 00995 } 00996 00997 void cSeca2ProvNL::PostCW(unsigned char *data) 00998 { 00999 const unsigned char *T1=SSET1(), *T2=SSET2(), *T3=CWT1(), *T4=SSEPT2(); 01000 unsigned char key[8]; 01001 unsigned int off2; 01002 01003 off2=data[2]^data[8+6]; 01004 key[2]=T4[off2]; key[5]=T4[(off2+key[2])&0xff]; 01005 01006 off2=(data[3]<<8)|data[8+4]; key[0]=T3[off2&0x1ff]; 01007 off2+=key[2]; key[4]=T3[off2&0x1ff]; 01008 01009 off2=(data[0]<<8)|data[8+7]; key[7]=T2[off2&0x7ff]; 01010 off2+=key[0]; key[1]=T2[off2&0x7ff]; 01011 01012 off2=(data[1]<<8)|data[8+5]; key[3]=T1[off2&0xbff]; 01013 off2+=key[4]; key[6]=T1[off2&0xbff]; 01014 01015 des.Des(data+4,key,SECA_DES_ENCR); 01016 } 01017 01018 void cSeca2ProvNL::ChainTableXor(unsigned char *data, unsigned short index) 01019 { 01020 static const unsigned short tabIdx[] = { 0x000, 0x4C3, 0x5D8, 0x63A, 0x471, 0x639, 0x417, 0x6CD }; 01021 static const unsigned char tabXor[] = { 0x84, 0xD6, 0x3A, 0x1F, 0x25, 0xB1, 0x7D, 0xF7 }; 01022 static const unsigned char tabPos1[] = { 2, 4, 3, 4, 5, 7, 6, 7 }; 01023 static const unsigned char tabPos2[] = { 3, 1, 5, 6, 0, 1, 0, 2 }; 01024 01025 unsigned int idx1, idx2; 01026 unsigned char xorVal=0; 01027 const unsigned char *T1=MT(), *T2=SSET1(); 01028 01029 idx1=(index^0x2B36) & 0x3FFF; 01030 idx2=idx1 & 0xBFF; 01031 for(int i=0; i<8; i++) { 01032 idx1=(idx1 + tabIdx[i]) & 0x3FFF; 01033 idx2=(idx2 + xorVal) & 0xBFF; 01034 xorVal ^= T1[idx1] ^ tabXor[i]; 01035 data[tabPos1[i]]^=xorVal; 01036 data[tabPos2[i]]^=T2[idx2]; 01037 } 01038 } 01039 01040 #undef beforeSig 01041 #undef afterSig 01042 01043 // -- Poland ------------------------------------------------------------------- 01044 01045 class cSeca2ProvPL : public cSeca2Prov { 01046 protected: 01047 virtual void PreCW(unsigned char *data); 01048 virtual void ChainTableXor(unsigned char *data, unsigned short index); 01049 public: 01050 cSeca2ProvPL(unsigned short Id); 01051 }; 01052 01053 static const unsigned short IdsPL[] = { 0x65,0 }; 01054 01055 static cSeca2ProvLinkReg<cSeca2ProvPL> staticLinkPL(IdsPL); 01056 01057 static const struct ProvData provDataPL = { 01058 0x65,16895,16895,0x96,0x69, { 3, 0, 0, 0, 2, 4, 3, 0 } 01059 }; 01060 01061 static const struct Perm ptPL[MAX_PERMS] = { 01062 { // 1 01063 { 2, 4, 4, 3, 2, 2, 4, 4 }, 01064 { 3, 2, 4, 3, 4, 4, 2, 3 }, 01065 { 0, 0, 0, 0, 0, 0, 0, 0 }, 01066 { 0, 0, 0, 0, 0, 0, 0, 0 } 01067 },{ // 2 01068 { 4, 4, 3, 2, 2, 3, 3, 4 }, 01069 { 4, 2, 3, 4, 3, 2, 4, 2 }, 01070 { 0, 0, 0, 0, 0, 0, 0, 0 }, 01071 { 0, 0, 0, 0, 0, 0, 0, 0 } 01072 },{ // 3 01073 },{ // 4 01074 },{ // 5 01075 },{ // 6 01076 },{ // 7 01077 },{ // 8 01078 },{ // 9 01079 { 4, 4, 3, 2, 3, 4, 3, 2 }, 01080 { 2, 4, 3, 2, 2, 4, 4, 3 }, 01081 { 2, 3, 4, 1, 0, 0, 0, 0 }, 01082 { 0, 0, 0, 0, 0, 0, 0, 0 }, 01083 },{ // 10 01084 } }; 01085 01086 cSeca2ProvPL::cSeca2ProvPL(unsigned short Id) 01087 :cSeca2Prov(Id) 01088 { 01089 pData=&provDataPL; perm=ptPL; 01090 } 01091 01092 void cSeca2ProvPL::PreCW(unsigned char *data) 01093 { 01094 static const unsigned char XT[]={ 0xA0,0x12,0x23,0x35,0x46,0xB0,0xDF,0xCA, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; 01095 static const unsigned char PT[]={ 0x05,0x04,0x06,0x07,0x03,0x00,0x01,0x02, 0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F }; 01096 unsigned char temp[16]; 01097 01098 xxor(temp,16,data,XT); 01099 for(int i=15; i>=0; i--) data[i]=temp[PT[i]]; 01100 } 01101 01102 void cSeca2ProvPL::ChainTableXor(unsigned char *data, unsigned short index) 01103 { 01104 const unsigned char *T1=MT(); 01105 for(int i=0; i<8; i++) data[i]^=T1[index++]; 01106 } 01107 01108 // -- Spain --------------------------------------------------------------------- 01109 01110 class cSeca2ProvSPA : public cSeca2Prov { 01111 protected: 01112 virtual void ChainTableXor(unsigned char *data, unsigned short index); 01113 public: 01114 cSeca2ProvSPA(unsigned short Id); 01115 }; 01116 01117 static const unsigned short IdsSPA[] = { 0x64,0x66,0x67,0 }; 01118 01119 static cSeca2ProvLinkReg<cSeca2ProvSPA> staticLinkSPA(IdsSPA); 01120 01121 static const struct ProvData provDataSPA = { 01122 0x64,16895,16895,0x96,0x69, { 2, 2, 2, 2, 2, 2, 2, 2 } 01123 }; 01124 01125 static const struct Perm ptSPA[MAX_PERMS] = { 01126 { // 1 01127 { 3, 2, 4, 3, 3, 4, 4, 2 }, 01128 { 4, 4, 3, 3, 2, 2, 4, 4 }, 01129 { 0, 0, 0, 0, 0, 0, 0, 0 }, 01130 { 0, 0, 0, 0, 0, 0, 0, 0 } 01131 },{ // 2 01132 { 2, 3, 4, 3, 2, 4, 3, 2 }, 01133 { 4, 3, 2, 3, 4, 2, 4, 3 }, 01134 { 0, 0, 0, 0, 0, 0, 0, 0 }, 01135 { 0, 0, 0, 0, 0, 0, 0, 0 } 01136 },{ // 3 01137 },{ // 4 01138 },{ // 5 01139 },{ // 6 01140 },{ // 7 01141 },{ // 8 01142 },{ // 9 01143 { 3, 3, 4, 4, 3, 3, 2, 2 }, 01144 { 3, 3, 2, 2, 3, 3, 2, 2 }, 01145 { 2, 3, 4, 1, 0, 0, 0, 0 }, 01146 { 0, 0, 0, 0, 0, 0, 0, 0 } 01147 },{ // 10 01148 } }; 01149 01150 cSeca2ProvSPA::cSeca2ProvSPA(unsigned short Id) 01151 :cSeca2Prov(Id) 01152 { 01153 pData=&provDataSPA; perm=ptSPA; 01154 } 01155 01156 void cSeca2ProvSPA::ChainTableXor(unsigned char *data, unsigned short index) 01157 { 01158 const unsigned char *T1=MT(); 01159 for(int i=0; i<8; i++) data[i]^=T1[index++]; 01160 } 01161 01162 // -- cSystemSeca --------------------------------------------------------------- 01163 01164 class cSystemSeca : public cSystem, private cSeca { 01165 private: 01166 cSeca2Prov *sp, *spL; 01167 int emmLenCnt; 01168 cDes des; 01169 cRSA rsa; 01170 // 01171 bool GetSeca2Prov(int provId, cSeca2Prov * &sp); 01172 bool Process0FNano(int count, unsigned char *hashDW, unsigned char *PK, const unsigned char *T1, const unsigned char *T2); 01173 bool Process51Nano(unsigned char *CW, const unsigned char *PermData, const unsigned char *hashDW, const unsigned char *T1, const unsigned char *T2, int provId); 01174 void Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode); 01175 void Permute(unsigned char *data, const unsigned char *pdata, const unsigned char *P); 01176 public: 01177 cSystemSeca(void); 01178 virtual ~cSystemSeca(); 01179 virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *data); 01180 virtual void ProcessEMM(int pid, int caid, const unsigned char *buffer); 01181 }; 01182 01183 cSystemSeca::cSystemSeca(void) 01184 :cSystem(SYSTEM_NAME,SYSTEM_PRI), 01185 des(secaPC1,secaPC2) 01186 { 01187 sp=spL=0; emmLenCnt=0; 01188 hasLogger=true; 01189 } 01190 01191 cSystemSeca::~cSystemSeca() 01192 { 01193 delete sp; 01194 delete spL; 01195 } 01196 01197 bool cSystemSeca::GetSeca2Prov(int provId, cSeca2Prov * &sp) 01198 { 01199 if(!sp || !sp->Matches(provId)) { 01200 delete sp; 01201 sp=cSeca2Providers::GetProv(provId); 01202 } 01203 return sp!=0; 01204 } 01205 01206 bool cSystemSeca::ProcessECM(const cEcmInfo *ecmD, unsigned char *data) 01207 { 01208 bool SE=false; 01209 unsigned char *ecm; 01210 const int msgLen=cParseSeca::Payload(data,(const unsigned char **)&ecm); 01211 const int keyNr=cParseSeca::KeyNr(data); 01212 01213 if(keyNr&0x80) { 01214 PRINTF(L_SYS_VERBOSE,"Super Encryption enabled"); 01215 SE=true; 01216 if(!GetSeca2Prov(ecmD->provId,sp)) { 01217 if(doLog) PRINTF(L_SYS_ECM,"Seca2 provider %04x not supported",ecmD->provId); 01218 return false; 01219 } 01220 } 01221 HEXDUMP(L_SYS_VERBOSE,data,SCT_LEN(data),"ECM:"); 01222 if(ecm[0]==0x10) { 01223 if(msgLen<0x5c) { 01224 if(doLog) PRINTF(L_SYS_ECM,"ECM length too small (%d)",msgLen); 01225 return false; 01226 } 01227 01228 if(SE) { 01229 HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM before SSE data modification :"); 01230 sp->PreSSE(ecm,msgLen-0x5a); 01231 HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM after SSE data modification :"); 01232 } 01233 01234 const int rsaKeynr=(ecm[1]&0x0F)+'0'; 01235 cBN exp, mod; 01236 cPlainKey *rsaKey; 01237 if(!(rsaKey=keys.FindKey('S',ecmD->provId,MBC('E',rsaKeynr),-1))) { 01238 if(doLog) PRINTF(L_SYS_KEY,"missing %04x E%c key",ecmD->provId,rsaKeynr); 01239 return false; 01240 } 01241 rsaKey->Get(exp); 01242 if(!(rsaKey=keys.FindKey('S',ecmD->provId,MBC('M',rsaKeynr),-1))) { 01243 if(doLog) PRINTF(L_SYS_KEY,"missing %04x M%c key",ecmD->provId,rsaKeynr); 01244 return false; 01245 } 01246 rsaKey->Get(mod); 01247 HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM before RSA decrypt :"); 01248 if(rsa.RSA(ecm+(msgLen-0x5a),ecm+(msgLen-0x5a),0x5a,exp,mod)!=0x5a) { 01249 PRINTF(L_SYS_CRYPTO,"RSA decrypt failed (ECM)"); 01250 return false; 01251 } 01252 HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM after RSA decrypt :"); 01253 01254 if(SE) { // PostSSE needed 01255 const int hashPtr=msgLen-ecm[msgLen-1]-9; 01256 if(hashPtr>=msgLen-9 || ecm[hashPtr]!=0x82) { 01257 PRINTF(L_SYS_CRYPTO,"RSA decrypt failed, signature pointer not found"); 01258 return false; 01259 } 01260 HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM before SSE result modification :"); 01261 sp->PostSSE(ecm,hashPtr); 01262 HEXDUMP(L_SYS_VERBOSE,ecm+(msgLen-0x5a),0x5a,"ECM after SSE result modification :"); 01263 } 01264 } 01265 01266 const unsigned char *T1=T1_S1, *T2=T2_S1; 01267 int decrLen=msgLen; 01268 if(SE) { 01269 if(!(T1=sp->T1(KEY2INDEX(keyNr))) || 01270 !(T2=sp->T2(KEY2INDEX(keyNr)))) return false; 01271 decrLen-=ecm[msgLen-1]; if(decrLen<8) return false; 01272 } 01273 01274 bool key8=!(cParseSeca::SysMode(data)&0x10); 01275 cPlainKey *pk=0; 01276 cKeySnoop ks(this,'S',ecmD->provId,keyNr&0x0F); 01277 unsigned char *buff=AUTOMEM(msgLen); 01278 while((pk=keys.FindKey('S',ecmD->provId,keyNr&0x0F,key8?8:16,pk))) { 01279 memcpy(buff,ecm,msgLen); // if decoding fails we need the original data 01280 01281 unsigned char PK[16], signature[20]; 01282 pk->Get(PK); 01283 if(key8) memcpy(&PK[8],&PK[0],8); // duplicate key 01284 01285 if(SE) { 01286 sp->CalcSHASignature(buff,decrLen-8,signature); 01287 LDUMP(L_SYS_VERBOSE,signature,8,"signature before encrypt :"); 01288 sp->SignatureMod(signature,PK); 01289 Encrypt(signature,PK,T1,T2); 01290 LDUMP(L_SYS_VERBOSE,signature,8,"signature after encrypt :"); 01291 01292 if(sp->DoSigCheck() && memcmp(signature,&buff[decrLen-8],8)) { 01293 PRINTF(L_SYS_VERBOSE,"signature check failed before SE decrypt"); 01294 continue; 01295 } 01296 HEXDUMP(L_SYS_VERBOSE,buff+2,msgLen-2,"ECM before SE decrypt :"); 01297 if(!sp->DecryptSE(buff+2,PK,msgLen-2,8,T1,T2)) { 01298 PRINTF(L_SYS_VERBOSE,"SE decrypt failed"); 01299 continue; 01300 } 01301 HEXDUMP(L_SYS_VERBOSE,buff+2,msgLen-2,"ECM after SE decrypt :"); 01302 } 01303 else { 01304 CalcSignature(buff,decrLen-8,signature,PK,T1,T2); 01305 } 01306 unsigned char hashDW[28]; // actually 16 bytes used for processing, but SHA needs more 01307 unsigned char *cCW=0; 01308 const unsigned char *nano51Data=0; 01309 int nr0F=0; 01310 01311 for(int i=0 ; i<decrLen; ) { 01312 int param=buff[i++]; 01313 int extra=(param >> 4) & 0x0f; 01314 switch(extra) { 01315 case 0x0d: extra=0x10; break; 01316 case 0x0e: extra=0x18; break; 01317 case 0x0f: extra=0x20; break; 01318 } 01319 switch(param) { 01320 case 0x0f: 01321 if(SE) nr0F++; 01322 break; 01323 case 0x51: 01324 if(SE) nano51Data=&buff[i]; 01325 break; 01326 case 0xd1: 01327 cCW=&buff[i]; 01328 if(SE) { 01329 sp->CalcSHASignature(buff,i,hashDW,false); 01330 memcpy(&hashDW[20],hashDW,8); 01331 Decrypt(&hashDW[20],PK,sp->T1(0),sp->T2(0)); 01332 sp->CalcSHASignature(hashDW,28,hashDW,false); 01333 } 01334 break; 01335 case 0x82: 01336 if((!SE || sp->DoSigCheck()) && memcmp(&buff[i],signature,8)) { 01337 PRINTF(L_SYS_VERBOSE,"signature check failed after decrypt"); 01338 cCW=0; i=decrLen; 01339 } 01340 break; 01341 } 01342 i+=extra; 01343 } 01344 if(cCW) { 01345 if(!nr0F || Process0FNano(nr0F,hashDW,PK,T1,T2)) { 01346 if(SE) sp->PreCW(cCW); 01347 if(!nano51Data || Process51Nano(cCW,nano51Data,hashDW,T1,T2,ecmD->provId)) { 01348 LDUMP(L_SYS_VERBOSE,cCW,16,"crypted CW :"); 01349 Decrypt(&cCW[0],PK,T1,T2); Decrypt(&cCW[8],PK,T1,T2); 01350 LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW :"); 01351 if(SE) { 01352 LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW before modification :"); 01353 sp->PostCW(cCW); 01354 LDUMP(L_SYS_VERBOSE,cCW,16,"decrypted CW after modification :"); 01355 } 01356 memcpy(cw,cCW,16); 01357 ks.OK(pk); 01358 return true; 01359 } 01360 } 01361 } 01362 } 01363 return false; 01364 } 01365 01366 bool cSystemSeca::Process0FNano(int count, unsigned char *hashDW, unsigned char *PK, const unsigned char *T1, const unsigned char *T2) 01367 { 01368 const unsigned char *MT=sp->MT(); 01369 unsigned char buffB[8]; 01370 01371 LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: initial hashDW:"); 01372 LDUMP(L_SYS_VERBOSE,PK,16,"0f: PK:"); 01373 while(count--) { 01374 unsigned char buffA[8]; 01375 swap8_4(hashDW); 01376 memcpy(buffA,hashDW,8); 01377 Decrypt(hashDW,PK,sp->T1(0),sp->T2(0)); 01378 LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: hashDW:"); 01379 01380 unsigned char buffE[8]; 01381 int off=WORD(hashDW,0,0x3FFF); 01382 xxor(buffE,8,&MT[off],&MT[0x3FFF-off]); 01383 xxor(buffE,8,&MT[( ((buffE[0] ^ hashDW[6])<<8) 01384 + (buffE[7] ^ hashDW[7]) )&0x3FFF],buffE); 01385 LDUMP(L_SYS_VERBOSE,buffE,8,"0f: buffE:"); 01386 01387 unsigned char buffC[16]; 01388 off=WORD(hashDW,2,0x3FFF); 01389 xxor(buffC,16,&MT[off],&MT[0x3FFF-off]); 01390 xxor(buffC,16,&MT[( ((hashDW[6] ^ buffC[0])<<8) 01391 + (hashDW[7] ^ buffC[15]) )&0x3FFF],buffC); 01392 LDUMP(L_SYS_VERBOSE,buffC,16,"0f: buffC:"); 01393 01394 off=WORD(hashDW,4,0x3FFF); 01395 for(int i=0; i<16; ++i) off=WORD(MT,off,0x3FFF); 01396 if(off+512 >= sp->MTSize()) { 01397 printf("BUG!!!: error: masking table overflow\n"); 01398 return false; 01399 } 01400 PRINTF(L_SYS_VERBOSE,"0f: off=%04x",off); 01401 01402 memcpy(buffB,buffE,8); 01403 Decrypt(buffB,buffC,&MT[off],&MT[off+256]); 01404 LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after 1st decr:"); 01405 xxor(buffB,8,buffB,buffE); 01406 LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after xor:"); 01407 Decrypt(buffB,PK,T1,T2); 01408 LDUMP(L_SYS_VERBOSE,buffB,8,"0f: buffB after 2nd decr:"); 01409 xxor(hashDW,8,buffA,buffB); 01410 } 01411 01412 for(int i=0; i<8; ++i) { 01413 PK[i] = buffB[i]; 01414 PK[i+8] = ~sn8(buffB[i]); 01415 } 01416 LDUMP(L_SYS_VERBOSE,hashDW,16,"0f: hashDW:"); 01417 LDUMP(L_SYS_VERBOSE,PK,16,"0f: new PK:"); 01418 return true; 01419 } 01420 01421 void cSystemSeca::Crypto51Nano(unsigned char *data, const unsigned char *key, const unsigned char crypto, const unsigned char mode) 01422 { 01423 switch(crypto) { 01424 case 0: // Xor 01425 PRINTF(L_SYS_VERBOSE,"51: XOR crypto selected"); 01426 xxor(data+0,8,key,data+0); xxor(data+8,8,key,data+8); 01427 break; 01428 case 1: // Seca crypto, with 9x table, always! 01429 { 01430 unsigned char PK[16]; 01431 const unsigned char *T1 = sp->T1(0); 01432 const unsigned char *T2 = sp->T2(0); 01433 memcpy(PK+0,key,8); memcpy(PK+8,key,8); 01434 PRINTF(L_SYS_VERBOSE,"51: SECA crypto selected: %s",mode?"decrypt":"encrypt"); 01435 if(mode) { Decrypt(data,PK,T1,T2); Decrypt(data+8,PK,T1,T2); } 01436 else { Encrypt(data,PK,T1,T2); Encrypt(data+8,PK,T1,T2); } 01437 break; 01438 } 01439 case 2: // DES crypto (Modified PC1,PC2) 01440 PRINTF(L_SYS_VERBOSE,"51: DES crypto selected: %s",mode?"decrypt":"encrypt"); 01441 if(mode) { des.Des(data,key,SECA_DES_DECR); des.Des(data+8,key,SECA_DES_DECR); } 01442 else { des.Des(data,key,SECA_DES_ENCR); des.Des(data+8,key,SECA_DES_ENCR); } 01443 break; 01444 case 3: // Additional Algo 01445 PRINTF(L_SYS_VERBOSE,"51: Additional crypto selected: %s",mode?"decrypt":"encrypt"); 01446 AdditionalAlgo(data,key,mode); AdditionalAlgo(data+8,key,mode); 01447 break; 01448 } 01449 } 01450 01451 bool cSystemSeca::Process51Nano(unsigned char *CW, const unsigned char *PermData, const unsigned char *hashDW, const unsigned char *T1, const unsigned char *T2, int provId) 01452 { 01453 const int pMode=(PermData[0]&0x3F)-1; 01454 const struct Perm *PT=sp->P(pMode); 01455 if(!PT) { 01456 PRINTF(L_SYS_VERBOSE,"51: failed to get permutation table"); 01457 return false; 01458 } 01459 unsigned char buffF[8], buffG[8]; 01460 switch(pMode) { 01461 case 0x00: 01462 case 0x01: 01463 { 01464 // Permutation 1 01465 Permute(buffF,PermData,PT->P1); 01466 LDUMP(L_SYS_VERBOSE,buffF,8,"51: buffF:"); 01467 xxor(buffG,8,buffF,hashDW); 01468 const int addAlgoMode=(PermData[0]&1)^1; 01469 for(int i=(PermData[1]&0x0f); i>0; i--) AdditionalAlgo(buffG,hashDW+8,addAlgoMode); 01470 // Permutation 2 01471 Permute(buffF,PermData,PT->P2); 01472 xxor(buffG,8,buffF,buffG); 01473 LDUMP(L_SYS_VERBOSE,buffG,8,"51: buffG:"); 01474 // Permutation 3 01475 Permute(buffF,PermData,PT->P3); 01476 xxor(buffG,8,buffF,buffG); 01477 // Permutation 4 01478 Permute(buffF,PermData,PT->P4); 01479 xxor(buffG,8,buffF,buffG); 01480 break; 01481 } 01482 case 0x08: 01483 { 01484 unsigned char buff1[128], buff2[64], buff3[9]; 01485 // prepare buffers for rsa data 01486 for(int i=0; i<20; i++) 01487 buff1[i]=buff2[i]=buff2[i+20]=buff2[i+40]=hashDW[i]; 01488 memcpy(buff3,PermData+2,3); 01489 for(int i=0; i<8; i++) buff1[i] = buff3[PT->P1[i]-2] ^= buff1[i]; 01490 LDUMP(L_SYS_VERBOSE,buff1,20,"51: permuted hashDW:"); 01491 for(int i=0; i<20; i++) 01492 buff1[i+24]=buff1[i+44]=buff1[i+68]=buff1[i+88]=buff1[i+108]=buff1[i]; 01493 LBSTARTF(L_SYS_VERBOSE); 01494 LBPUT("51: nano51Data:"); 01495 for(int i=0; i<4; i++) { 01496 unsigned char t=PermData[PT->P3[i]]; 01497 if(PT->P3[i]==1) t&=0x0F; 01498 buff1[i+20]=buff1[i+64]=buff2[i+60]=t; 01499 LBPUT(" %02x",t); 01500 } 01501 LBEND(); 01502 HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1:"); 01503 HEXDUMP(L_SYS_VERBOSE,buff2,64,"51: buff2:"); 01504 01505 memcpy(buff3,buff1,9); 01506 for(int j=0; j<64; j++) { // XOR even with buff2, odd with 0xFF 01507 buff1[ j*2 ] ^= buff2[j]; 01508 buff1[(j*2)+1] ^= 0xFF; 01509 } 01510 HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1 rsa prepped:"); 01511 01512 // RSA decrypt 01513 { 01514 cBN exp, mod; 01515 cPlainKey *pk; 01516 if(!(pk=keys.FindKey('S',provId,MBC3('E','9',N51_MAGIC),-1))) { 01517 if(doLog) PRINTF(L_SYS_KEY,"missing %04x N51 E9 key",provId); 01518 return false; 01519 } 01520 pk->Get(exp); 01521 if(!(pk=keys.FindKey('S',provId,MBC3('M','9',N51_MAGIC),-1))) { 01522 if(doLog) PRINTF(L_SYS_KEY,"missing %04x N51 M9 key",provId); 01523 return false; 01524 } 01525 pk->Get(mod); 01526 if(rsa.RSA(buff1,buff1,128,exp,mod)<9) return false; 01527 HEXDUMP(L_SYS_VERBOSE,buff1,128,"51: buff1 rsa decrypted:"); 01528 } 01529 01530 unsigned int sum=0; 01531 for(int j=0; j<9; j++) { 01532 unsigned int nextSum=(buff1[j]&0x80) ? 1:0; 01533 buff1[j]=(sum+2*buff1[j])^buff3[j]; 01534 sum=nextSum; 01535 } 01536 LDUMP(L_SYS_VERBOSE,buff1,9,"51: buff1 after sumalgo:"); 01537 01538 memcpy(buffG,buff1,8); 01539 memcpy(buff3,PermData+2,3); 01540 for(int i=0; i<8; i++) buffG[i] = buff3[PT->P2[i]-2] ^= buffG[i]; 01541 break; 01542 } 01543 01544 default: 01545 PRINTF(L_SYS_VERBOSE,"51: data incorrect or proccessing not needed"); 01546 return false; 01547 } 01548 LDUMP(L_SYS_VERBOSE,buffG,8,"51: cryptokey:"); 01549 Crypto51Nano(CW,buffG,(PermData[1]>>6)&3,PermData[0]&0x80); 01550 // Final Permutation 01551 Permute(buffF,PermData,sp->FP()); 01552 xxor(CW+0,8,CW+0,buffF); xxor(CW+8,8,CW+8,buffF); 01553 LDUMP(L_SYS_VERBOSE,hashDW,8,"51: cryptokey:"); 01554 Crypto51Nano(CW,hashDW,(PermData[1]>>4)&0x03,PermData[0]&0x40); 01555 LDUMP(L_SYS_VERBOSE,CW,16,"51: new encrypted CW:"); 01556 return true; 01557 } 01558 01559 void cSystemSeca::Permute(unsigned char *data, const unsigned char *pdata, const unsigned char *P) 01560 { 01561 for(int i=7; i>=0; i--) data[i] = P[i] ? pdata[P[i]] : 0; 01562 } 01563 01564 void cSystemSeca::ProcessEMM(int pid, int caid, const unsigned char *buffer) 01565 { 01566 if(buffer[0]!=0x84) return; // we only support shared updates 01567 01568 int msgLen=cParseSeca::CmdLen(buffer); 01569 if(msgLen!=0x55 && msgLen!=0x63) { 01570 if(++emmLenCnt<=5) 01571 PRINTF(L_SYS_EMM,"length of EMM does not match (%02x <> 55/63)%s",msgLen,emmLenCnt==5 ? " ....":""); 01572 return; 01573 } 01574 emmLenCnt=0; 01575 unsigned char *emm; 01576 msgLen=cParseSeca::Payload(buffer,(const unsigned char **)&emm); 01577 int provId=cParseSeca::ProvId(buffer); 01578 bool SE=false; 01579 const unsigned char *T1=T1_S1, *T2=T2_S1; 01580 int decrLen=msgLen; 01581 if(emm[0]==0x10) { // de-SSE 01582 const int rsaKeynr = emm[1]+'0'; 01583 cPlainKey *pk; 01584 cBN exp, mod; 01585 01586 if(!(pk=keys.FindKeyNoTrig('S',provId,MBC3('E',rsaKeynr,EMM_MAGIC),-1))) return; 01587 pk->Get(exp); 01588 if(!(pk=keys.FindKeyNoTrig('S',provId,MBC3('M',rsaKeynr,EMM_MAGIC),-1))) return; 01589 pk->Get(mod); 01590 01591 if(rsa.RSA(emm+2,emm+2,msgLen-2,exp,mod)!=msgLen-2) return; 01592 const int keyNr=cParseSeca::KeyNr(buffer); 01593 if(keyNr&0x80) { 01594 SE=true; 01595 decrLen-=emm[msgLen-1]; 01596 if(!GetSeca2Prov(provId,spL) || 01597 !(T1=spL->T1(KEY2INDEX(keyNr))) || 01598 !(T2=spL->T2(KEY2INDEX(keyNr))) || 01599 decrLen<8) return; 01600 } 01601 } 01602 01603 unsigned char *buff=AUTOMEM(msgLen); 01604 for(cSecaCardInfo *ci=Scards.First(); ci; ci=Scards.Next(ci)) { 01605 if(ci->MatchEMM(buffer) || (CheckNull(ci->sa,sizeof(ci->sa)) && ci->MatchID(buffer))) { 01606 unsigned char MK[16]; 01607 if(cParseSeca::SysMode(buffer)&0x10) { 01608 if(ci->KeySize()!=16) continue; // don't bother 01609 memcpy(&MK[0],ci->key,16); 01610 } 01611 else { 01612 memcpy(&MK[0],ci->key,8); 01613 memcpy(&MK[8],ci->key,8); 01614 } 01615 01616 unsigned char signature[20]; 01617 memcpy(buff,emm,msgLen); // if decoding fails we need the original de-sse'd data 01618 01619 if(!SE) { 01620 for(int i=0 ; i<=64 && i<msgLen-8; i+=8) Decrypt(&buff[i],MK,T1,T2); 01621 CalcSignature(buff,decrLen-8,signature,MK,T1,T2); 01622 } 01623 else { 01624 spL->CalcSHASignature(buff,decrLen-8,signature); 01625 Encrypt(signature,MK,T1,T2); 01626 if(memcmp(signature,&buff[decrLen-8],8) || 01627 !spL->DecryptSE(buff+2,MK,msgLen-2,0,T1,T2)) continue; 01628 } 01629 01630 unsigned char keyN[4], *key[4]; 01631 int pos, len; 01632 unsigned int numKeys=0; 01633 bool sigOk=false; 01634 for(pos=0 ; pos<decrLen ; pos+=len) { 01635 int cmd=buff[pos++]; 01636 len=(cmd>>4)&0x0f; 01637 switch(len) { 01638 case 0x0b: len=0x0e; break; 01639 case 0x0d: len=0x10; break; 01640 case 0x0e: len=0x18; break; 01641 case 0x0f: len=0x20; break; 01642 } 01643 switch(cmd) { 01644 case 0x82: // signature 01645 if(!memcmp(signature,&buff[pos],8)) sigOk=true; 01646 pos=decrLen; 01647 break; 01648 case 0x90: // new primary key 01649 if(numKeys<sizeof(keyN)) { 01650 keyN[numKeys]=buff[pos] & 0x0f; 01651 key[numKeys]=&buff[pos+1]; 01652 numKeys++; 01653 } 01654 break; 01655 } 01656 } 01657 char str[20],str2[20],str3[20]; 01658 if(sigOk) { 01659 LBSTARTF(L_SYS_EMM); 01660 LBPUT("ID %s SA %s",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3)); 01661 LBPUT(" - OK (CI ID %s SA %s KEY01 %s)",HexStr(str,ci->provId,2),HexStr(str2,ci->sa,3),HexStr(str3,ci->key,8)); 01662 for(unsigned int i=0 ; i<numKeys ; i++) { 01663 Decrypt(key[i],MK,T1,T2); 01664 LBPUT(" KEY %02x %s",keyN[i],HexStr(str,key[i],8)); 01665 FoundKey(); 01666 if(keys.NewKey('S',provId,keyN[i],key[i],8)) NewKey(); 01667 } 01668 LBEND(); 01669 break; 01670 } 01671 else if(!CheckNull(ci->sa,sizeof(ci->sa))) 01672 PRINTF(L_SYS_EMM,"ID %s SA %s - FAIL",HexStr(str,SID(buffer),2),HexStr(str2,SA(buffer),3)); 01673 } 01674 } 01675 return; 01676 } 01677 01678 // -- cSystemLinkSeca ---------------------------------------------------------- 01679 01680 class cSystemLinkSeca : public cSystemLink { 01681 public: 01682 cSystemLinkSeca(void); 01683 virtual bool CanHandle(unsigned short SysId); 01684 virtual cSystem *Create(void) { return new cSystemSeca; } 01685 }; 01686 01687 static cSystemLinkSeca staticInit; 01688 01689 cSystemLinkSeca::cSystemLinkSeca(void) 01690 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI) 01691 { 01692 Feature.NeedsKeyFile(); 01693 } 01694 01695 bool cSystemLinkSeca::CanHandle(unsigned short SysId) 01696 { 01697 SysId&=SYSTEM_MASK; 01698 return SYSTEM_CAN_HANDLE(SysId); 01699 }