|
SASC-NG
DVBSoftCAM
|
00001 /* 00002 * Softcam plugin to VDR (C++) 00003 * 00004 * This code is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This code is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 * Or, point your browser to http://www.gnu.org/copyleft/gpl.html 00018 */ 00019 00020 #include <stdlib.h> 00021 #include <string.h> 00022 #include <ctype.h> 00023 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 }