📄 nagra.cpp
字号:
/*
* Softcam plugin to VDR (C++)
*
* This code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to http://www.gnu.org/copyleft/gpl.html
*/
#include "stdafx.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//#include <unistd.h>
#include "common.h"
#include "debug.h"
#include "nagra.h"
#include "win32lacks.h"
#include "xnprintf.h"
#include <openssl/bn.h>
#include "openssl-compat.h"
//////
//#include <vdr/tools.h>
int minEcmTime=400; // ms
// -- cPlainKeyNagra -----------------------------------------------------------
#define PLAINLEN_NAGRA_H 8
#define PLAINLEN_NAGRA_I 16
#define PLAINLEN_NAGRA_B 64
#define PLAINLEN_NAGRA_IE 24
#define PLAINLEN_NAGRA_BE 96
static cPlainKeyTypeReg<cPlainKeyNagra,'N'> KeyReg;
cPlainKeyNagra::cPlainKeyNagra(bool Super)
:cDualKey(Super,true)
{}
bool cPlainKeyNagra::IsBNKey(void) const
{
switch(keynr & C2MASK) {
// Nagra1
case MBC('M','1'):
case MBC('E','1'):
case MBC('N','1'):
case MBC('N','2'):
// Nagra2
case MBC(N2_MAGIC,N2_EMM_G_R):
case MBC(N2_MAGIC,N2_EMM_S_R):
case MBC(N2_MAGIC,N2_EMM_G_R|N2_EMM_SEL):
case MBC(N2_MAGIC,N2_EMM_S_R|N2_EMM_SEL):
return true;
}
//******** EMM-S Keys Modification - 12/26/06
// EMM-s key check
if ((keynr>>24) == N2_EMM_S) {
switch(keynr & 0xFF) {
case N2_EMM_S_R:
case N2_EMM_G_R:
//printf("*** IsBNKey=%02X %02X***\n",(keynr>>24),(keynr & 0xFF));
return true;
}
//******** EMM-S Keys Modification - 12/26/06
}
return false;
}
int cPlainKeyNagra::ParseTag(const char *tag, const char * &line)
{
int r=-1;
const int l=strlen(tag);
if(!strncasecmp(line,tag,l)) {
line+=l; r=0;
while(*line!=0 && isdigit(*line)) {
r=r*10 + *line-'0';
line++;
}
line=skipspace(line);
}
return r;
}
void cPlainKeyNagra::GetTagDef(int nr, int &romnr, int &pk, int &keytype)
{
romnr =DEF_ROM;
pk =DEF_PK;
keytype=DEF_TYPE;
nr&=C2MASK;
if(nr=='V' || nr==MBC('N','2') || nr==MBC('M','1'))
pk=0; // different default
}
bool cPlainKeyNagra::Parse(const char *line)
{
unsigned char sid[2];
const char *sline=line;
int len;
if(GetChar(line,&type,1) && (len=GetHex(line,sid,2,false))) {
type=toupper(type); id=Bin2Int(sid,len);
line=skipspace(line);
bool ok;
if(!strncasecmp(line,"NN",2)) {
line=skipspace(line+2);
unsigned char skeynr;
if((ok=GetHex(line,&skeynr,1)))
keynr=MBC(N2_MAGIC,skeynr);
//printf("NN keynr = %2x [%s]\n",keynr,line);
}
//******** EMM-S Keys Modification - 12/26/06
else if (!strncasecmp(line,"S",1)) {
int CamID = 0;
int tempValue = 0;
int CamByte[3];
char camnr[7];
bool CamExisting = false;
memset(camnr,'\0',7);
char tempstring[3];
memset(tempstring,'\0',3);
line=skipspace(line+2);
sprintf(camnr,"%.6s",line);
for (int it=0; it<6; it+=2) {
sprintf(tempstring,"%c%c",camnr[it],camnr[it+1]);
CamByte[tempValue] = strtol(tempstring,NULL,16);
//CamID = MBC(CamID,CamByte[tempValue]);
//CamID ^= CamByte[tempValue]; //XOR values to get seed
tempValue++;
}
for (int is=0; is<keys.EMMptr; is++) {
if ( keys.EMMs[is][0] == CamByte[0] &&
keys.EMMs[is][1] == CamByte[1] &&
keys.EMMs[is][2] == CamByte[2] )
CamExisting = true;
}
CamID=CID(N2_EMM_S,CamByte[0],CamByte[1],CamByte[2]);
//printf("*** %02x %02x %02x - CID = %06X\n",CamByte[0],CamByte[1],CamByte[2],CamID);
if (CamExisting == false) {
keys.EMMs[keys.EMMptr][0] = CamByte[0];
keys.EMMs[keys.EMMptr][1] = CamByte[1];
keys.EMMs[keys.EMMptr][2] = CamByte[2];
keys.EMMs[keys.EMMptr][3] = CamID;
////printf("*** EMMptr = %02d [%02x %02x %02x %02x %02x %02x]\n",keys.EMMptr,keys.EMMs[keys.EMMptr][0],keys.EMMs[keys.EMMptr][1],keys.EMMs[keys.EMMptr][2],CamByte[0],CamByte[1],CamByte[2]);
keys.EMMptr++;
}
line=skipspace(line+6);
unsigned char skeynr;
if((ok=GetHex(line,&skeynr,1)))
keynr=MBC(CamID,skeynr);
// keynr=MBC(MBC(0x53,CamID),skeynr); // 0x53 = 'S'
// keynr=MBC(CamID,skeynr);
// printf("S keynr = (%X) [%s]\n",keynr,line);
}
//******** EMM-S Keys Modification - 12/26/06
else {
bool tags;
switch(toupper(*line)) {
case 'E':
case 'N': ok=GetChar(line,&keynr,2); tags=true; break;
case 'M': ok=GetChar(line,&keynr,2); tags=false; break;
case 'V': ok=GetChar(line,&keynr,1); tags=true; break;
default: {
unsigned char skeynr;
ok=GetHex(line,&skeynr,1); keynr=skeynr; tags=false; break;
}
//printf("keynr = %2x\n",keynr);
}
if(ok) {
int romnr, pk, keytype;
GetTagDef(keynr,romnr,pk,keytype);
line=skipspace(line);
while(tags) {
int r;
if((r=ParseTag("ROM",line))>=0) {
if(r>0 && r<=15) romnr=r;
else d(printf("nagrakey: ignoring bad ROM number %d\n",r));
}
else if((r=ParseTag("TYP",line))>=0) {
if(r>=0 && r<=1) keytype=r;
else d(printf("nagrakey: ignoring bad key type %d\n",r));
}
else if((r=ParseTag("PK",line))>=0) {
if(r>=0 && r<=2) pk=r;
else d(printf("nagrakey: ignoring bad PK key number %d\n",pk));
}
else {
tags=false;
if(pk!=0 && (keynr=='V' || keynr==MBC('N','2'))) {
pk=0;
d(printf("nagrakey: auto-adjusting to PK0 for N2/V key\n"))
}
if(romnr!=0 && keytype!=1) {
keytype=1;
d(printf("nagrakey: auto-adjusting to TYP1 for ROM key\n"))
}
}
}
if(IsBNKey() || keynr=='V') keynr=ADDC3(keynr,KEYSET(romnr,pk,keytype));
}
}
unsigned char skey[PLAINLEN_NAGRA_BE];
int keylen=PLAINLEN_NAGRA_BE;
len=GetHex(line,skey,keylen,false);
if( (!IsBNKey() && (len==PLAINLEN_NAGRA_H || len==PLAINLEN_NAGRA_I || len==PLAINLEN_NAGRA_IE))
|| ( IsBNKey() && (len==PLAINLEN_NAGRA_B || len==PLAINLEN_NAGRA_BE)))
keylen=len;
if(len==keylen) {
if((keynr=='V' || keynr==MBC(N2_MAGIC,0x03) || keynr==MBC(N2_MAGIC,(0x03|N2_EMM_SEL))) && CheckNull(skey,len))
d(printf("nagrakey: FAKE verify keys will cause problems. Please remove them!\n"))
SetKey(skey,len);
return true;
}
}
// FormatError("nagra",sline);
d(printf("nagrakey: bad key format '%s'\n",sline))
return false;
}
cString cPlainKeyNagra::PrintKeyNr(void)
{
if(C2(keynr)==N2_MAGIC)
return cString::sprintf("NN %.2X",keynr&0xFF);
int k=keynr & C2MASK;
if(!IsBNKey() && k!='V')
return cString::sprintf("%.2X",keynr);
char nr[32];
int q=0;
if(IsBNKey()) nr[q++]=(keynr>>8) & 0xff;
nr[q++]=keynr & 0xff;
nr[q]=0;
int romnr, pk, keytype;
GetTagDef(keynr,romnr,pk,keytype);
if(ROM(keynr) !=romnr ) q+=_snprintf(nr+q,sizeof(nr)-q," ROM%d",ROM(keynr));
if(PK(keynr) !=pk ) q+=_snprintf(nr+q,sizeof(nr)-q," PK%d",PK(keynr));
if(TYPE(keynr)!=keytype) q+=_snprintf(nr+q,sizeof(nr)-q," TYP%d",TYPE(keynr));
return nr;
}
// -- cNagra -------------------------------------------------------------------
cNagra::cNagra(void)
{
BN_set_word(pubExp,3);
}
void cNagra::CreateRSAPair(const unsigned char *key, const unsigned char *data, BIGNUM *e, BIGNUM *m)
{
// Calculate P and Q from data
cBN p,q;
CreatePQ(key,p,q);
ExpandPQ(p,q,data,e,m);
}
void cNagra::ExpandPQ(BIGNUM *p, BIGNUM *q, const unsigned char *data, BIGNUM *e, BIGNUM *m)
{
// Calculate N=P*Q (modulus)
cBNctx ctx;
BN_mul(m,p,q,ctx);
if(data) BN_bin2bn(data,64,e); // set provided data as E1
else { // else calculate the 'official' one
// E = ( ( ( (P-1) * (Q-1) * 2) + 1) / 3)
BN_sub_word(p,1);
BN_sub_word(q,1);
BN_mul(e,p,q,ctx);
BN_mul_word(e,2);
BN_add_word(e,1);
BN_div_word(e,3);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -