SASC
DVBSoftCAM

seca.c

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