📄 newcamd.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 <string.h>#include <stdlib.h>#include <crypt.h>#include <byteswap.h>#include <vdr/thread.h>#include "cc.h"#include "network.h"#include "misc.h"#include "parse.h"#include <openssl/des.h>#define CWS_NETMSGSIZE 240// -- cTripleDes ---------------------------------------------------------------class cTripleDes {private: DES_key_schedule ks1,ks2; // void SetOddParity(unsigned char *key); // key must be 16 bytes!protected: unsigned char desKey[16]; // void ScheduleKey(void); int PadMessage(unsigned char *data, int len); void Expand(unsigned char *expanded, const unsigned char *normal); // 14 byte key input, 16 byte expanded output void Decrypt(unsigned char *data, int len); const unsigned char *Encrypt(const unsigned char *data, int len, unsigned char *crypt); };void cTripleDes::SetOddParity(unsigned char *key){ DES_set_odd_parity((DES_cblock *)&key[0]); // set odd parity on both keys DES_set_odd_parity((DES_cblock *)&key[8]); // }void cTripleDes::ScheduleKey(void){ DES_key_sched((DES_cblock *)&desKey[0],&ks1); DES_key_sched((DES_cblock *)&desKey[8],&ks2);}void cTripleDes::Expand(unsigned char *expand, const unsigned char *normal){ expand[0] = normal[0] & 0xfe; expand[1] = ((normal[0] << 7) | (normal[1] >> 1)) & 0xfe; expand[2] = ((normal[1] << 6) | (normal[2] >> 2)) & 0xfe; expand[3] = ((normal[2] << 5) | (normal[3] >> 3)) & 0xfe; expand[4] = ((normal[3] << 4) | (normal[4] >> 4)) & 0xfe; expand[5] = ((normal[4] << 3) | (normal[5] >> 5)) & 0xfe; expand[6] = ((normal[5] << 2) | (normal[6] >> 6)) & 0xfe; expand[7] = normal[6] << 1; expand[8] = normal[7] & 0xfe; expand[9] = ((normal[7] << 7) | (normal[8] >> 1)) & 0xfe; expand[10] = ((normal[8] << 6) | (normal[9] >> 2)) & 0xfe; expand[11] = ((normal[9] << 5) | (normal[10] >> 3)) & 0xfe; expand[12] = ((normal[10] << 4) | (normal[11] >> 4)) & 0xfe; expand[13] = ((normal[11] << 3) | (normal[12] >> 5)) & 0xfe; expand[14] = ((normal[12] << 2) | (normal[13] >> 6)) & 0xfe; expand[15] = normal[13] << 1; SetOddParity(expand);}int cTripleDes::PadMessage(unsigned char *data, int len){ DES_cblock padBytes; unsigned char noPadBytes; noPadBytes = (8 - ((len - 1) % 8)) % 8; if(len+noPadBytes+1 >= CWS_NETMSGSIZE-8) { PRINTF(L_CC_NEWCAMD,"message overflow in cTripleDes::PadMessage"); return -1; } srand(time(NULL)); // make sure the random generator is initialized DES_random_key((DES_cblock *)padBytes); memcpy(data+len,padBytes,noPadBytes); len+=noPadBytes; data[len]=XorSum(data+2,len-2); return len+1;}const unsigned char *cTripleDes::Encrypt(const unsigned char *data, int len, unsigned char *crypt){ DES_cblock ivec; DES_random_key((DES_cblock *)ivec); memcpy(crypt+len,ivec,sizeof(ivec)); DES_ede2_cbc_encrypt(data+2,crypt+2,len-2,&ks1,&ks2,(DES_cblock *)ivec,DES_ENCRYPT); return crypt;}void cTripleDes::Decrypt(unsigned char *data, int len){ if((len-2) % 8 || (len-2)<16) { PRINTF(L_CC_NEWCAMD,"warning: encrypted data size mismatch"); return; } DES_cblock ivec; len-=sizeof(ivec); memcpy(ivec, data+len, sizeof(ivec)); DES_ede2_cbc_encrypt(data+2,data+2,len-2,&ks1,&ks2,(DES_cblock *)ivec,DES_DECRYPT);}// -- cNewCamdClient -----------------------------------------------------------#define USERLEN 32#define PASSWDLEN 32#define CWS_FIRSTCMDNO 0xe0typedef enum { MSG_CLIENT_2_SERVER_LOGIN = CWS_FIRSTCMDNO, MSG_CLIENT_2_SERVER_LOGIN_ACK, MSG_CLIENT_2_SERVER_LOGIN_NAK, MSG_CARD_DATA_REQ, MSG_CARD_DATA, MSG_SERVER_2_CLIENT_NAME, MSG_SERVER_2_CLIENT_NAME_ACK, MSG_SERVER_2_CLIENT_NAME_NAK, MSG_SERVER_2_CLIENT_LOGIN, MSG_SERVER_2_CLIENT_LOGIN_ACK, MSG_SERVER_2_CLIENT_LOGIN_NAK, MSG_ADMIN, MSG_ADMIN_ACK, MSG_ADMIN_LOGIN, MSG_ADMIN_LOGIN_ACK, MSG_ADMIN_LOGIN_NAK, MSG_ADMIN_COMMAND, MSG_ADMIN_COMMAND_ACK, MSG_ADMIN_COMMAND_NAK } net_msg_type_t;typedef enum { COMMTYPE_CLIENT, COMMTYPE_SERVER } comm_type_t;struct CustomData { union { struct { unsigned short prgId; // Big-Endian unsigned char data[6]; } V525; struct { unsigned int prgId; // Big-Endian } V520; }; };class cCardClientNewCamd : public cCardClient, private cTripleDes, private cIdSet {private: cNetSocket so; unsigned char configKey[14]; unsigned short netMsgId; int caId, protoVers, cdLen; bool emmProcessing; char username[USERLEN], password[PASSWDLEN]; // void InitVars(void); void InitProtoVers(int vers); bool NextProto(void); void InitCustomData(struct CustomData *cd, const unsigned short PrgId, const unsigned char *data); void PrepareLoginKey(unsigned char *deskey, const unsigned char *rkey, const unsigned char *ckey);protected: virtual bool Login(void);public: cCardClientNewCamd(const char *Name); // Client Helper functions bool SendMessage(cNetSocket *so, const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd=0, comm_type_t commType=COMMTYPE_CLIENT); int ReceiveMessage(cNetSocket *so, unsigned char *data, bool UseMsgId, struct CustomData *cd=0, comm_type_t commType=COMMTYPE_CLIENT); bool CmdSend(cNetSocket *so, net_msg_type_t cmd, comm_type_t commType=COMMTYPE_CLIENT); int CmdReceive(cNetSocket *so, comm_type_t commType=COMMTYPE_CLIENT); // virtual bool Init(const char *CfgDir); virtual bool CanHandle(unsigned short SysId); virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw); virtual bool ProcessEMM(int caSys, const unsigned char *data); };static cCardClientLinkReg<cCardClientNewCamd> __ncd("Newcamd");cCardClientNewCamd::cCardClientNewCamd(const char *Name):cCardClient(Name),so(DEFAULT_CONNECT_TIMEOUT,20,DEFAULT_IDLE_TIMEOUT){ memset(username,0,sizeof(username)); memset(password,0,sizeof(password)); InitVars(); InitProtoVers(525);}void cCardClientNewCamd::InitVars(void){ netMsgId=0; caId=-1; emmProcessing=false; ResetIdSet();}void cCardClientNewCamd::InitProtoVers(int vers){ switch(vers) { case 525: protoVers=525; cdLen=8; break; default: protoVers=520; cdLen=4; break; } PRINTF(L_CC_NEWCAMD,"now using protocol version %d (cdLen=%d)",protoVers,cdLen);}bool cCardClientNewCamd::NextProto(void){ switch(protoVers) { case 525: InitProtoVers(520); break; default: return false; } return true;}void cCardClientNewCamd::InitCustomData(struct CustomData *cd, const unsigned short PrgId, const unsigned char *data){ if(cd) { switch(protoVers) { case 525: cd->V525.prgId=bswap_16(PrgId); if(data) memcpy(cd->V525.data,data,sizeof(cd->V525.data)); else memset(cd->V525.data,0,sizeof(cd->V525.data)); break; default: cd->V520.prgId=bswap_32((unsigned int)PrgId); break; } }}void cCardClientNewCamd::PrepareLoginKey(unsigned char *deskey, const unsigned char *rkey, const unsigned char *ckey){ unsigned char tmpkey[14]; for (int i=0; i<(int)sizeof(tmpkey); i++) { tmpkey[i]=rkey[i]^ckey[i]; } Expand(deskey, tmpkey);}bool cCardClientNewCamd::SendMessage(cNetSocket *so, const unsigned char *data, int len, bool UseMsgId, const struct CustomData *cd, comm_type_t commType){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -