SASC-NG
DVBSoftCAM

conax.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 
00024 #include "system-common.h"
00025 #include "crypto.h"
00026 #include "data.h"
00027 #include "misc.h"
00028 #include "log-sys.h"
00029 #include "version.h"
00030 
00031 SCAPIVERSTAG();
00032 
00033 #define SYSTEM_CONAX         0x0B00
00034 
00035 #define SYSTEM_NAME          "Conax"
00036 #define SYSTEM_PRI           -10
00037 #define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_CONAX)
00038 
00039 #define L_SYS        3
00040 #define L_SYS_ALL    LALL(L_SYS_LASTDEF)
00041 
00042 static const struct LogModule lm_sys = {
00043   (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK,
00044   (LMOD_ENABLE|L_SYS_DEFDEF)&LOPT_MASK,
00045   "conax",
00046   { L_SYS_DEFNAMES }
00047   };
00048 ADD_MODULE(L_SYS,lm_sys)
00049 
00050 // -- cSystemConax ---------------------------------------------------------------
00051 
00052 class cSystemConax : public cSystem {
00053 private:
00054   cRSA rsa;
00055   //
00056   void ParseECM(unsigned char *buf, int len);
00057 public:
00058   cSystemConax(void);
00059   virtual bool ProcessECM(const cEcmInfo *ecm, unsigned char *source);
00060   };
00061 
00062 cSystemConax::cSystemConax(void)
00063 :cSystem(SYSTEM_NAME,SYSTEM_PRI)
00064 {}
00065 
00066 void cSystemConax::ParseECM(unsigned char *buf, int len)
00067 {
00068   int i=0;
00069   while(i<len) {
00070     int nano=buf[i++];
00071     int nanolen=buf[i++];
00072     
00073     switch(nano) {
00074       case 0x80:
00075       case 0x82:
00076         ParseECM(buf+i+3,nanolen-3); break;
00077       case 0x81:
00078         ParseECM(buf+i+2,nanolen-2); break;
00079       case 0x30:
00080         memcpy(cw  ,buf+i+10,8);
00081         memcpy(cw+8,buf+i+2 ,8);
00082         break;
00083       }
00084     i+=nanolen;
00085     }
00086 }
00087 
00088 bool cSystemConax::ProcessECM(const cEcmInfo *ecm, unsigned char *source)
00089 {
00090   int length=source[4]-2;
00091   const int keyid=source[6];
00092   const int nano=source[5];
00093   source+=7;
00094 
00095   cKeySnoop ks(this,'C',keyid,'M');
00096   cPlainKey *pk;
00097   cBN mod, exp;
00098   if(!(pk=keys.FindKey('C',keyid,'E',-1))) {
00099     if(doLog) PRINTF(L_SYS_KEY,"missing %02X E key",keyid);
00100     return false;
00101     }
00102   pk->Get(exp);
00103   if(!(pk=keys.FindKey('C',keyid,'M',-1))) {
00104     if(doLog) PRINTF(L_SYS_KEY,"missing %02X M key",keyid);
00105     return false;
00106     }
00107   pk->Get(mod);
00108 
00109   for(int i=length ; i>0 ;) {
00110     int index=i-64;
00111     if(index<0) index=0;
00112     if(rsa.RSA(source+index,source+index,64,exp,mod,false)<=0) {
00113       if(doLog) PRINTF(L_SYS_CRYPTO,"RSA failed");
00114       return false;
00115       }
00116     if(nano==0x63) {
00117       // nano 0x63 block only decodes to 63 bytes
00118       memmove(source+index,source+index+1,length-(index+1));
00119       length-=1;
00120       }
00121     i-=(i%60 && index) ? i%60 : 64;
00122     }
00123 
00124   static const unsigned char hash[] = { 0x05,0x00,0x05 };
00125   if(memcmp(hash,source+2,3) || memcmp(source+5,source+length-5,3)) {
00126     if(doLog) PRINTF(L_SYS_ECM,"signature check failed");
00127     return false;
00128     }
00129 
00130   ParseECM(source+10,length-10);
00131   ks.OK(pk);
00132   return true;
00133 }
00134 
00135 // -- cPlainKeyConax --------------------------------------------------------------
00136 
00137 #define PLAINLEN_CONAX 64
00138 
00139 class cPlainKeyConax : public cBNKey {
00140 protected:
00141   virtual cString PrintKeyNr(void);
00142 public:
00143   cPlainKeyConax(bool Super);
00144   virtual bool Parse(const char *line);
00145   };
00146 
00147 static cPlainKeyTypeReg<cPlainKeyConax,'C'> KeyReg;
00148 
00149 cPlainKeyConax::cPlainKeyConax(bool Super)
00150 :cBNKey(Super)
00151 {}
00152 
00153 bool cPlainKeyConax::Parse(const char *line)
00154 {
00155   unsigned char sid, skey[PLAINLEN_CONAX];
00156   if(GetChar(line,&type,1) && GetHex(line,&sid,1) &&
00157      GetChar(line,&keynr,1) && GetHex(line,skey,PLAINLEN_CONAX)) {
00158     type=toupper(type); keynr=toupper(keynr); id=sid;
00159     SetBinKey(skey,PLAINLEN_CONAX);
00160     return true;
00161     }
00162   return false;
00163 }
00164 
00165 cString cPlainKeyConax::PrintKeyNr(void)
00166 {
00167   return cString::sprintf("%c",keynr);
00168 }
00169 
00170 // -- cSystemLinkConax ---------------------------------------------------------
00171 
00172 class cSystemLinkConax : public cSystemLink {
00173 public:
00174   cSystemLinkConax(void);
00175   virtual bool CanHandle(unsigned short SysId);
00176   virtual cSystem *Create(void) { return new cSystemConax; }
00177   };
00178 
00179 static cSystemLinkConax staticInit;
00180 
00181 cSystemLinkConax::cSystemLinkConax(void)
00182 :cSystemLink(SYSTEM_NAME,SYSTEM_PRI)
00183 {
00184   Feature.NeedsKeyFile();
00185 }
00186 
00187 bool cSystemLinkConax::CanHandle(unsigned short SysId)
00188 {
00189   SysId&=SYSTEM_MASK;
00190   return SYSTEM_CAN_HANDLE(SysId);
00191 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines