📄 sc-nagra.c
字号:
/* * 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 <stdio.h>#include <stdlib.h>#include <string.h>#include <openssl/rand.h>#include "system-common.h"#include "smartcard.h"#include "crypto.h"#include "helper.h"#include "log-sc.h"#include "log-core.h"#define SYSTEM_NAGRA 0x1801#define SYSTEM_NAME "SC-Nagra"#define SYSTEM_PRI -5#define SYSTEM_CAN_HANDLE(x) ((x)==SYSTEM_NAGRA)#define SC_NAME "Nagra"#define SC_ID MAKE_SC_ID('N','a','g','r')#define L_SC 11#define L_SC_PROC LCLASS(L_SC,L_SC_LASTDEF<<1)#define L_SC_ALL LALL(L_SC_PROC)static const struct LogModule lm_sc = { (LMOD_ENABLE|L_SC_ALL)&LOPT_MASK, (LMOD_ENABLE|L_SC_DEFDEF|L_SC_PROC)&LOPT_MASK, "sc-nagra", { L_SC_DEFNAMES,"process" } };ADD_MODULE(L_SC,lm_sc)// -- cSystemScNagra ---------------------------------------------------------------------class cSystemScNagra : public cSystemScCore {public: cSystemScNagra(void); };cSystemScNagra::cSystemScNagra(void):cSystemScCore(SYSTEM_NAME,SYSTEM_PRI,SC_ID,"SC Nagra"){ hasLogger=true;}// -- cSystemLinkScNagra --------------------------------------------------------------class cSystemLinkScNagra : public cSystemLink {public: cSystemLinkScNagra(void); virtual bool CanHandle(unsigned short SysId); virtual cSystem *Create(void) { return new cSystemScNagra; } };static cSystemLinkScNagra staticInit;cSystemLinkScNagra::cSystemLinkScNagra(void):cSystemLink(SYSTEM_NAME,SYSTEM_PRI){ Feature.NeedsSmartCard();}bool cSystemLinkScNagra::CanHandle(unsigned short SysId){ return smartcards.HaveCard(SC_ID) && SYSTEM_CAN_HANDLE(SysId);}// -- cCamCryptNagra ------------------------------------------------------------------class cCamCryptNagra {private: cIDEA idea; cRSA rsa; cBN camMod, camExp; bool hasMod; unsigned char sk[16]; // void Signature(unsigned char *sig, const unsigned char *key, const unsigned char *msg, int len);public: cCamCryptNagra(void); void InitCamKey(unsigned char *key, const unsigned char *bk, const unsigned char *data); void SetCamMod(BIGNUM *m); bool DecryptCamMod(const unsigned char *dt08, const unsigned char *key, const unsigned char *key2, BIGNUM *m); bool DecryptCamData(unsigned char *out, const unsigned char *key, const unsigned char *in); bool DecryptCW(unsigned char *dcw, const unsigned char *in); };cCamCryptNagra::cCamCryptNagra(void){ hasMod=false; BN_set_word(camExp,3);}void cCamCryptNagra::Signature(unsigned char *sig, const unsigned char *key, const unsigned char *msg, int len){ unsigned char buff[16]; memcpy(buff,key,16); for(int i=0; i<len; i+=8) { IdeaKS ks; idea.SetEncKey(buff,&ks); idea.Encrypt(msg+i,8,buff,&ks,0); xxor(buff,8,buff,&msg[i]); //for(int j=7; j>=0; j--) buff[j]^=msg[i+j]; memcpy(&buff[8],buff,8); } memcpy(sig,buff,8);}void cCamCryptNagra::InitCamKey(unsigned char *key, const unsigned char *bk, const unsigned char *data){ memcpy(key,bk,8); int d=UINT32_LE(data); BYTE4_LE(key+8 , d); BYTE4_LE(key+12,~d); //memcpy(key+8,data,4); //for(int i=0; i<4; i++) key[i+12]=~data[i];}void cCamCryptNagra::SetCamMod(BIGNUM *m){ BN_copy(camMod,m); hasMod=true;}bool cCamCryptNagra::DecryptCamMod(const unsigned char *dt08, const unsigned char *key, const unsigned char *cardid, BIGNUM *m){ unsigned char buff[72]; if(rsa.RSA(buff,dt08+13,64,camExp,m)!=64) return false; memcpy(buff+64,dt08+13+64,8); buff[63]|=dt08[12]&0x80; IdeaKS dks; idea.SetDecKey(key,&dks); idea.Decrypt(buff,72,&dks,0); unsigned char sig[8]; memcpy(sig,buff,8); memset(buff+0,0,4); memcpy(buff+4,cardid,4); Signature(buff,key,buff,72); BN_bin2bn(buff+8,64,camMod); if(memcmp(sig,buff,8)) { PRINTF(L_SC_PROC,"DT08 signature failed. Check boxkey/IRD modulus"); return false; } hasMod=true; return true;}bool cCamCryptNagra::DecryptCamData(unsigned char *out, const unsigned char *key, const unsigned char *camdata){ if(!hasMod) return false; //decrypt $2A data here and prepare $2B reply if(rsa.RSA(out,camdata,64,camExp,camMod)!=64) return false; Signature(sk,key,out,32); memcpy(sk+8,sk,8); Signature(sk+8,sk,out,32);; if(rsa.RSA(out,out,64,camExp,camMod)!=64) return false; LDUMP(L_SC_PROC,sk,16,"established session key ->"); return true;}bool cCamCryptNagra::DecryptCW(unsigned char *dcw, const unsigned char *ecw){ const int nCw=ecw[4]/2; if(nCw<10) return false; IdeaKS ks; ecw+=5; idea.SetDecKey(sk,&ks); memcpy(dcw+8,ecw +2,8); memcpy(dcw+0,ecw+nCw+2,8); idea.Decrypt(dcw+0,8,&ks,0); idea.Decrypt(dcw+8,8,&ks,0); return true;}// -- cSmartCardDataNagra ------------------------------------------------------class cSmartCardDataNagra : public cSmartCardData {public: bool global; int provId; unsigned char bk[8]; cBN mod; // cSmartCardDataNagra(void); cSmartCardDataNagra(int ProvId, bool Global); virtual bool Parse(const char *line); virtual bool Matches(cSmartCardData *param); };cSmartCardDataNagra::cSmartCardDataNagra(void):cSmartCardData(SC_ID) {}cSmartCardDataNagra::cSmartCardDataNagra(int ProvId, bool Global=false):cSmartCardData(SC_ID){ provId=ProvId; global=Global;}bool cSmartCardDataNagra::Matches(cSmartCardData *param){ cSmartCardDataNagra *cd=(cSmartCardDataNagra *)param; return (cd->provId==provId) && (cd->global==global);}bool cSmartCardDataNagra::Parse(const char *line){ unsigned char buff[512]; line=skipspace(line); if(*line++!='[' || GetHex(line,buff,2)!=2 || *(line=skipspace(line))!=']' ) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: provider id"); return false; } provId=buff[0]*256+buff[1]; line=skipspace(line+1); if(!strncasecmp(line,"IRDMOD",6)) { global=true; line+=6; } if(GetHex(line,bk,sizeof(bk),false)<=0) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: boxkey"); return false; } int l=GetHex(line,buff,sizeof(buff),false); if(l!=64) { PRINTF(L_CORE_LOAD,"smartcarddatanagra: format error: %s",global?"IRDMOD":"CAMMOD"); return false; } BN_bin2bn(buff,l,mod); return true;}// -- cSmartCardNagra -----------------------------------------------------------------// ISO 7816 T=1 defines#define NAD(a) (a[0])#define PCB(a) (a[1])#define LEN(a) (a[2])#define CLA(a) (a[3])#define INS(a) (a[4])#define P1(a) (a[5])#define P2(a) (a[6])#define L(a) (a[7])// Nagra NAD and reply NAD#define N2_NAD 0x21#define N2_R_NAD sn8(N2_NAD)#define N2_CLA 0xA0#define N2_INS 0xCA#define N2_P1 0x00#define N2_P2 0x00#define N2_CMD(a) (a[8])#define N2_CLEN(a) (a[9]) #define N2_DATA(a) (a[10]) #define SETIFS 0xC1#define CAMDATA 0x08// Datatypes#define IRDINFO 0x00#define TIERS 0x05#define MAX_REC 20// Card Status checks
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -