📄 viaccess.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 <string.h>
#include "regex.h"
#include "common.h"
#include "sc.h"
#include "system.h"
#include "system-common.h"
#include "data.h"
#include "misc.h"
#include "crypto.h"
#include "parse.h"
#include "network.h"
#include "opts.h"
#include "win32lacks.h"
#define SYSTEM_VIACCESS 0x0500
#define SYSTEM_NAME "Viaccess"
#define SYSTEM_PRI -10
#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_VIACCESS)
static char AESKeyHost[30]="213.251.166.40";
static int AESKeyPort=80;
static char AESKeyPath[30]="~aes/aes/";
//#define DEBUG_LOG
#ifdef DEBUG_LOG
#define dl(x) { (x); }
#else
#define dl(x) ;
#endif
// -- cPlainKeyVia -------------------------------------------------------------
#define VIA1_KEYLEN 8
#define VIA2_KEYLEN 16
#define VIATPS_KEYLEN 16
class cPlainKeyVia : public cPlainKeyStd {
protected:
virtual cString PrintKeyNr(void);
public:
cPlainKeyVia(bool Super);
virtual bool Parse(const char *line);
virtual bool SetKey(void *Key, int Keylen);
};
static cPlainKeyTypeReg<cPlainKeyVia,'V',false> KeyReg;
cPlainKeyVia::cPlainKeyVia(bool Super)
:cPlainKeyStd(Super)
{}
bool cPlainKeyVia::SetKey(void *Key, int Keylen)
{
if(keynr==MBC3('T','P','S')) SetSupersede(false);
return cPlainKeyStd::SetKey(Key,Keylen);
}
bool cPlainKeyVia::Parse(const char *line)
{
unsigned char sid[3], skeynr, skey[VIA2_KEYLEN];
#ifdef DEBUG
const char *sline=line;
#endif
int len;
if(GetChar(line,&type,1) && (len=GetHex(line,sid,3,false))) {
type=toupper(type); id=Bin2Int(sid,len);
line=skipspace(line);
bool ok=false;
if(!strncasecmp(line,"TPS",3)) {
line+=3;
keynr=MBC3('T','P','S');
ok=(len=GetHex(line,skey,VIATPS_KEYLEN));
}
else if(GetHex(line,&skeynr,1)) {
keynr=skeynr;
ok=((len=GetHex(line,skey,VIA2_KEYLEN,false)) && (len==VIA1_KEYLEN || len==VIA2_KEYLEN));
}
if(ok) {
SetKey(skey,len);
return true;
}
}
d(printf("plainkeyvia: bad key format '%s'\n",sline))
return false;
}
cString cPlainKeyVia::PrintKeyNr(void)
{
return cString::sprintf((keynr==MBC3('T','P','S'))?"TPS":"%02X",keynr);
}
// -- cViaccessCardInfo --------------------------------------------------------
class cViaccessCardInfo : public cSimpleItem {
public:
unsigned char ID[3], UA[5], SA[4], KEYNO[1], KEY[8];
//
bool Parse(const char *line);
bool Save(FILE *f) { return true; }
bool IsUpdated(void) { return false; }
void Updated(void) {}
bool Cmp(cViaccessCardInfo *ci) { return false; }
};
bool cViaccessCardInfo::Parse(const char *line)
{
return GetHex(line,ID,sizeof(ID)) &&
GetHex(line,UA,sizeof(UA)) &&
GetHex(line,SA,sizeof(SA)) &&
GetHex(line,KEYNO,sizeof(KEYNO)) &&
GetHex(line,KEY,sizeof(KEY));
}
// -- cViaccessCardInfos -------------------------------------------------------
class cViaccessCardInfos : public cCardInfos<cViaccessCardInfo> {
public:
cViaccessCardInfos(void):cCardInfos<cViaccessCardInfo>(SYSTEM_NAME) {}
};
static cViaccessCardInfos Vcards;
// -- cViaccess ----------------------------------------------------------------
class cViaccess : protected cDes {
private:
unsigned char v2key[8];
bool v2mode;
//
int HashNanos(const unsigned char *data, int len);
void Via2Mod(const unsigned char *key2, unsigned char *data);
protected:
unsigned char hbuff[8], hkey[8];
int pH;
//
void SetV2Mode(const unsigned char *key2);
void SetHashKey(const unsigned char *key);
void HashByte(unsigned char c);
void HashClear(void);
void Hash(void);
//
void Decode(unsigned char *data, const unsigned char *key);
bool Decrypt(const unsigned char *work_key, const unsigned char *data, int len, unsigned char *des_data1, unsigned char *des_data2);
//
virtual unsigned int Mod(unsigned int R, unsigned int key7) const;
public:
cViaccess(void);
};
cViaccess::cViaccess(void)
:cDes()
{
v2mode=false;
}
/* viaccess DES modification */
unsigned int cViaccess::Mod(unsigned int R, unsigned int key7) const
{
if(key7!=0) {
const unsigned int key5=(R>>24)&0xff;
unsigned int al=key7*key5 + key7 + key5;
al=(al&0xff)-((al>>8)&0xff);
if(al&0x100) al++;
R=(R&0x00ffffffL) + (al<<24);
}
return R;
}
/* viaccess2 modification. Extracted from "Russian wafer" card.
A lot of thanks to it's author :) */
void cViaccess::Via2Mod(const unsigned char *key2, unsigned char *data)
{
int kb, db;
for(db=7; db>=0; db--) {
for(kb=7; kb>3; kb--) {
int a0=kb^db;
int pos=7;
if(a0&4) { a0^=7; pos^=7; }
a0=(a0^(kb&3)) + (kb&3);
if(!(a0&4)) data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
}
}
for(db=0; db<8; db++) {
for(kb=0; kb<4; kb++) {
int a0=kb^db;
int pos=7;
if(a0&4) { a0^=7; pos^=7; }
a0=(a0^(kb&3)) + (kb&3);
if(!(a0&4)) data[db]^=(key2[kb] ^ ((data[kb^pos]*key2[kb^4]) & 0xFF));
}
}
}
void cViaccess::Decode(unsigned char *data, const unsigned char *key)
{
if(v2mode) Via2Mod(v2key,data);
Des(data,key,VIA_DES);
if(v2mode) Via2Mod(v2key,data);
}
void cViaccess::SetV2Mode(const unsigned char *key2)
{
if(key2) {
memcpy(v2key,key2,sizeof(v2key));
v2mode=true;
}
else v2mode=false;
}
void cViaccess::SetHashKey(const unsigned char *key)
{
memcpy(hkey,key,sizeof(hkey));
}
void cViaccess::HashByte(unsigned char c)
{
hbuff[pH++]^=c;
if(pH==8) { pH=0; Hash(); }
}
void cViaccess::HashClear(void)
{
memset(hbuff,0,sizeof(hbuff));
pH=0;
}
void cViaccess::Hash(void)
{
if(v2mode) Via2Mod(v2key,hbuff);
Des(hbuff,hkey,VIA_DES_HASH);
if(v2mode) Via2Mod(v2key,hbuff);
}
int cViaccess::HashNanos(const unsigned char *data, int len)
{
int i=0;
pH=0;
if(data[0]==0x9f) {
HashByte(data[i++]);
HashByte(data[i++]);
for(int j=0; j<data[1]; j++) HashByte(data[i++]);
while(pH!=0) HashByte(0);
}
for(; i<len; i++) HashByte(data[i]);
return i;
}
bool cViaccess::Decrypt(const unsigned char *work_key, const unsigned char *data, int len, unsigned char *des_data1, unsigned char *des_data2)
{
int pos=0, encStart=0;
unsigned char signatur[8];
while(pos<len) {
switch(data[pos]) {
case 0xea: // encrypted bytes
encStart = pos + 2;
memcpy(des_data1,&data[pos+2],8);
memcpy(des_data2,&data[pos+2+8],8);
break;
case 0xf0: // signature
memcpy(signatur,&data[pos+2],8);
break;
}
pos += data[pos+1]+2;
}
HashClear();
SetHashKey(work_key);
// key preparation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -