|
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 "nagra.h" 00025 #include "nagra-def.h" 00026 #include "log-nagra.h" 00027 #include "log-core.h" 00028 #include "version.h" 00029 00030 SCAPIVERSTAG(); 00031 00032 static const struct LogModule lm_sys = { 00033 (LMOD_ENABLE|L_SYS_ALL)&LOPT_MASK, 00034 (LMOD_ENABLE|L_SYS_DEFDEF|L_SYS_EMU|L_SYS_DISASM80|L_SYS_MAP)&LOPT_MASK, 00035 "nagra", 00036 { L_SYS_DEFNAMES,"emu","disasm","disasm80","cpuStats","map","rawemm","rawecm" } 00037 }; 00038 ADD_MODULE(L_SYS,lm_sys) 00039 00040 int minEcmTime=400; // ms 00041 00042 // -- cPlainKeyNagra ----------------------------------------------------------- 00043 00044 #define PLAINLEN_NAGRA_H 8 00045 #define PLAINLEN_NAGRA_I 16 00046 #define PLAINLEN_NAGRA_B 64 00047 #define PLAINLEN_NAGRA_IE 24 00048 #define PLAINLEN_NAGRA_BE 96 00049 00050 static cPlainKeyTypeReg<cPlainKeyNagra,'N'> KeyReg; 00051 00052 cPlainKeyNagra::cPlainKeyNagra(bool Super) 00053 :cDualKey(Super,true) 00054 {} 00055 00056 bool cPlainKeyNagra::IsBNKey(int kn) 00057 { 00058 switch(kn & C2MASK) { 00059 // Nagra1 00060 case MBC('M','1'): 00061 case MBC('E','1'): 00062 case MBC('N','1'): 00063 case MBC('N','2'): 00064 // Nagra2 00065 case MBC(N2_MAGIC,N2_EMM_G_R): 00066 case MBC(N2_MAGIC,N2_EMM_S_R): 00067 case MBC(N2_MAGIC,N2_EMM_G_R|N2_EMM_SEL): 00068 case MBC(N2_MAGIC,N2_EMM_S_R|N2_EMM_SEL): 00069 return true; 00070 } 00071 return false; 00072 } 00073 00074 bool cPlainKeyNagra::IsBNKey(void) const 00075 { 00076 return IsBNKey(keynr); 00077 } 00078 00079 int cPlainKeyNagra::ParseTag(const char *tag, const char * &line) 00080 { 00081 int r=-1; 00082 const int l=strlen(tag); 00083 if(!strncasecmp(line,tag,l)) { 00084 line+=l; r=0; 00085 while(*line!=0 && isdigit(*line)) { 00086 r=r*10 + *line-'0'; 00087 line++; 00088 } 00089 line=skipspace(line); 00090 } 00091 return r; 00092 } 00093 00094 void cPlainKeyNagra::GetTagDef(int nr, int &romnr, int &pk, int &keytype) 00095 { 00096 romnr =DEF_ROM; 00097 pk =DEF_PK; 00098 keytype=DEF_TYPE; 00099 nr&=C2MASK; 00100 if(nr=='V' || nr==MBC('N','2') || nr==MBC('M','1')) 00101 pk=0; // different default 00102 } 00103 00104 bool cPlainKeyNagra::Parse(const char *line) 00105 { 00106 unsigned char sid[2]; 00107 int len; 00108 if(GetChar(line,&type,1) && (len=GetHex(line,sid,2,false))) { 00109 type=toupper(type); id=Bin2Int(sid,len); 00110 line=skipspace(line); 00111 bool ok; 00112 if(!strncasecmp(line,"NN",2)) { 00113 line=skipspace(line+2); 00114 unsigned char skeynr; 00115 if((ok=GetHex(line,&skeynr,1))) 00116 keynr=MBC(N2_MAGIC,skeynr); 00117 } 00118 else { 00119 bool tags; 00120 switch(toupper(*line)) { 00121 case 'E': 00122 case 'N': ok=GetChar(line,&keynr,2); tags=true; break; 00123 case 'M': ok=GetChar(line,&keynr,2); tags=false; break; 00124 case 'V': ok=GetChar(line,&keynr,1); tags=true; break; 00125 default: { 00126 unsigned char skeynr; 00127 ok=GetHex(line,&skeynr,1); keynr=skeynr; tags=false; break; 00128 } 00129 } 00130 if(ok) { 00131 int romnr, pk, keytype; 00132 GetTagDef(keynr,romnr,pk,keytype); 00133 line=skipspace(line); 00134 while(tags) { 00135 int r; 00136 if((r=ParseTag("ROM",line))>=0) { 00137 if(r>0 && r<=15) romnr=r; 00138 else PRINTF(L_CORE_LOAD,"nagrakey: ignoring bad ROM number %d",r); 00139 } 00140 else if((r=ParseTag("TYP",line))>=0) { 00141 if(r>=0 && r<=1) keytype=r; 00142 else PRINTF(L_CORE_LOAD,"nagrakey: ignoring bad key type %d",r); 00143 } 00144 else if((r=ParseTag("PK",line))>=0) { 00145 if(r>=0 && r<=2) pk=r; 00146 else PRINTF(L_CORE_LOAD,"nagrakey: ignoring bad PK key number %d",pk); 00147 } 00148 else { 00149 tags=false; 00150 if(pk!=0 && (keynr=='V' || keynr==MBC('N','2'))) { 00151 pk=0; 00152 PRINTF(L_CORE_LOAD,"nagrakey: auto-adjusting to PK0 for N2/V key"); 00153 } 00154 if(romnr!=0 && keytype!=1) { 00155 keytype=1; 00156 PRINTF(L_CORE_LOAD,"nagrakey: auto-adjusting to TYP1 for ROM key"); 00157 } 00158 } 00159 } 00160 if(IsBNKey() || keynr=='V') keynr=ADDC3(keynr,KEYSET(romnr,pk,keytype)); 00161 } 00162 } 00163 00164 unsigned char skey[PLAINLEN_NAGRA_BE]; 00165 int keylen=PLAINLEN_NAGRA_BE; 00166 len=GetHex(line,skey,keylen,false); 00167 if( (!IsBNKey() && (len==PLAINLEN_NAGRA_H || len==PLAINLEN_NAGRA_I || len==PLAINLEN_NAGRA_IE)) 00168 || ( IsBNKey() && (len==PLAINLEN_NAGRA_B || len==PLAINLEN_NAGRA_BE))) 00169 keylen=len; 00170 if(len==keylen) { 00171 if((keynr=='V' || keynr==MBC(N2_MAGIC,0x03) || keynr==MBC(N2_MAGIC,(0x03|N2_EMM_SEL))) && CheckNull(skey,len)) 00172 PRINTF(L_GEN_WARN,"nagrakey: FAKE verify keys will cause problems. Please remove them!"); 00173 SetBinKey(skey,len); 00174 return true; 00175 } 00176 } 00177 return false; 00178 } 00179 00180 cString cPlainKeyNagra::PrintKeyNr(void) 00181 { 00182 if(C2(keynr)==N2_MAGIC) 00183 return cString::sprintf("NN %.2X",keynr&0xFF); 00184 int k=keynr & C2MASK; 00185 if(!IsBNKey() && k!='V') 00186 return cString::sprintf("%.2X",keynr); 00187 char nr[32]; 00188 int q=0; 00189 if(IsBNKey()) nr[q++]=(keynr>>8) & 0xff; 00190 nr[q++]=keynr & 0xff; 00191 nr[q]=0; 00192 int romnr, pk, keytype; 00193 GetTagDef(keynr,romnr,pk,keytype); 00194 if(ROM(keynr) !=romnr ) q+=snprintf(nr+q,sizeof(nr)-q," ROM%d",ROM(keynr)); 00195 if(PK(keynr) !=pk ) q+=snprintf(nr+q,sizeof(nr)-q," PK%d",PK(keynr)); 00196 if(TYPE(keynr)!=keytype) q+=snprintf(nr+q,sizeof(nr)-q," TYP%d",TYPE(keynr)); 00197 return nr; 00198 } 00199 00200 // -- cNagra ------------------------------------------------------------------- 00201 00202 cNagra::cNagra(void) 00203 { 00204 BN_set_word(pubExp,3); 00205 } 00206 00207 void cNagra::CreateRSAPair(const unsigned char *key, const unsigned char *data, BIGNUM *e, BIGNUM *m) 00208 { 00209 // Calculate P and Q from data 00210 cBN p,q; 00211 CreatePQ(key,p,q); 00212 ExpandPQ(p,q,data,e,m); 00213 } 00214 00215 void cNagra::ExpandPQ(BIGNUM *p, BIGNUM *q, const unsigned char *data, BIGNUM *e, BIGNUM *m) 00216 { 00217 // Calculate N=P*Q (modulus) 00218 cBNctx ctx; 00219 BN_mul(m,p,q,ctx); 00220 if(data) BN_bin2bn(data,64,e); // set provided data as E1 00221 else { // else calculate the 'official' one 00222 // E = ( ( ( (P-1) * (Q-1) * 2) + 1) / 3) 00223 BN_sub_word(p,1); 00224 BN_sub_word(q,1); 00225 BN_mul(e,p,q,ctx); 00226 BN_mul_word(e,2); 00227 BN_add_word(e,1); 00228 BN_div_word(e,3); 00229 } 00230 }