SASC-NG
DVBSoftCAM

nagra.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 "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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines