⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bjst.c

📁 在原来基础上新添加了对ST、V、I、C卡的处理
💻 C
字号:
/*
本代码仅作为学习研究之目的使用,请您于24小时内自觉将其删除,请勿应用于商业活动或其它赢利性活动中,
否则后果自负!
*/


/******************************************************
 * 文件名:bjst.c
 * 功  能:处理BCA命令
 * 作  者:
 * 日  期:
 *****************************************************/

#include "bjst.h"

Bjst_Info_t* pstBjstInfo = NULL;

static Smart_ErrorCode_t bjst_transfer(Smart_Handle_t Handle,
								   U8*			    ins,
								   U16			   NumberToWrite,
								   U8*			   Response,
								   U16*			   Read,
								   U8* Status);//数据传输
static bool bjst_begincmd(Smart_Handle_t Handle);
static bool bjst_get_key(Smart_Handle_t Handle);//读取key,用作将卡中送出的cw解密
static bool bjst_get_sn(Smart_Handle_t Handle);//读取智能卡号

static U8 keywords[9] = {0};//读取key,用作将卡中送出的cw解密


/************************************************************************/
/* 初始化, 主要工作是读取卡内的基本信息,如卡号、运营商等信息
   
   输入     handle -- smart card 句柄
   输出     无
   返回值   true -- 初始化成功 false -- 初始化失败
   其他                                                                 */
/************************************************************************/
bool bjst_init(Smart_Handle_t handle)
{
	pstBjstInfo = &bjst;
	memset(pstBjstInfo,0,sizeof(Bjst_Info_t));

	if(!bjst_begincmd(handle))
	{
		printf("bjst init : get ppua failed !!\n");
//		return false;
	}


	if(!bjst_get_sn(handle))
	{
		printf("bjst init : get sn failed !!\n");
//		return false;
	}

	if(!bjst_get_key(handle))
	{
		printf("bjst init : get key failed !!\n");
		return false;
	}

	printf("bjst Init OK !!\n");
	return true;
}


/************************************************************************/
/* 起始指令,  这三个命令在智能卡 Reset 后必须首先执行,之后才可以执行其他的命令 

   输入     Handle -- smart card 句柄
   输出     无
   返回值   true -- 命令执行成功 false -- 命令执行失败
   其他                                    
                                                                       */
/************************************************************************/
static bool bjst_begincmd(Smart_Handle_t Handle)
{
	U8	response[50]={0};
	U16 cmdlen	=0;
	U16	resplen =0;
	U8  pbword[2]={0};
	Smart_ErrorCode_t bresult=SMC_NO_ERROR;
	int i = 0;

	U8 cmd1[100] = {0x00, 0x84, 0x00, 0x00, 0x10};
	U8 cmd2[100] = {0x00, 0x0C, 0x00, 0x00, 0x10};
	U8 cmd3[100] = {0x00, 0x0B, 0x00, 0x00, 0x10};

	cmdlen = 5;
	bresult=bjst_transfer(Handle,cmd1,cmdlen,response,&resplen,pbword);

	if(bresult!=SMC_NO_ERROR)
	{
		bresult=bjst_transfer(Handle,cmd1,cmdlen,response,&resplen,pbword);
	}

	memcpy(cmd2+5,response,8);
    cmd2[13] = 0x56;

    cmdlen = 14;

	bresult=bjst_transfer(Handle,cmd2,cmdlen,response,&resplen,pbword);

	if(bresult!=SMC_NO_ERROR)
	{
		bresult=bjst_transfer(Handle,cmd2,cmdlen,response,&resplen,pbword);
		return false;
	}
	
	memcpy(cmd3+5,response,8);
    cmd3[13] = 0x56;

    cmdlen = 14;
	bresult=bjst_transfer(Handle,cmd3,cmdlen,response,&resplen,pbword);

	if(bresult!=SMC_NO_ERROR)
	{
		bresult=bjst_transfer(Handle,cmd3,cmdlen,response,&resplen,pbword);
		return false;
	}
	
	return true;
}

/************************************************************************/
/* 读取智能卡号,就是st卡片上显示的数字,也用来做授权寻址

   输入     Handle -- smart card 句柄
   输出     无
   返回值   true -- 获取卡号成功 false -- 获取卡号失败
   其他     得到的卡号存储于全局变量pstBjstInfo中,可用于OSD显示                               

通讯示例:


00 00 05 81 D4 00 01 05 54 
00 00 07 00 xx xx xx xx 90 00   //卡号 xx xx xx xx (十六进制)                     */
/************************************************************************/


static bool bjst_get_sn(Smart_Handle_t Handle)
{
	U8	cmd[]={0x81,0xD4,0x00,0x01,0x05};
	U8	response[100];
	U8	pbword[2]={0};
	U16	cmdlen=0;
	U16	replen=0;
	Smart_ErrorCode_t bresult=SMC_NO_ERROR;
	
	cmdlen = 5;

	bresult=bjst_transfer(Handle,cmd,cmdlen,response,&replen,pbword);

	if((bresult!=SMC_NO_ERROR)&&(replen<5))
	{
		printf("数据错误 \n");
		return false;
	}
	
	pstBjstInfo->uCardNumber=(response[1]<<24)+(response[2]<<16)+(response[3]<<8)+response[4];
	printf("card number = %8d\n", pstBjstInfo->uCardNumber);
	return true;
}



/************************************************************************/
/* 读取加密cw的密钥,在将ECM传给智能卡,智能卡解出CW传给机顶盒的时候就是用
这组数做的加密(虽然算法比较简单,但是至少是有这个意识的,所以很鄙视tf和sm的
做法,还到处宣扬什么安全性,无语...),其实当时弄这个地方还是花费了不少时间的!

   输入     Handle -- smart card 句柄
   输出     无
   返回值   true -- 读取数据成功 false -- 读取数据失败
   其他     得到的信息存储于全局变量keywords中                               

通讯示例:


00 00 05 81 D0 00 01 08 5D 
00 00 0A xx xx xx xx xx xx xx xx 90 00                      */
/************************************************************************/

bool bjst_get_key(Smart_Handle_t Handle)
{
	U8	cmd[]={0x81,0xD0,0x00,0x01,0x08};
	U8	response[100];
	U8	pbword[2]={0};
	U16	cmdlen=0;
	U16	replen=0;
	Smart_ErrorCode_t bresult=SMC_NO_ERROR;
	
	int i = 0;

	cmdlen = 5;

	bresult=bjst_transfer(Handle,cmd,cmdlen,response,&replen,pbword);

	if((bresult!=SMC_NO_ERROR)&&(replen<5))
	{
		printf("数据错误 \n");
		return false;
	}
	
	memcpy(keywords, response, 8);

	return true;
}

/************************************************************************/
/* 处理解析ECM,得到CW,得到它我们就可以看节目了!收取ECM的时候设置filter
的第一个字节0x80/0x81就ok了

   输入     Handle -- smart card 句柄  buf -- ECM信息,从0x80/0x81开始
   输出     pucCW  -- 就是cw啦,16个字节,不是奇偶,就是奇偶,根据情况你自己试验
   返回值   true -- 解析ECM成功 false --解析ECM失败
   其他       
                                                                        */
/************************************************************************/
bool bjst_parse_ecm(Smart_Handle_t Handle,U8* buf,U8* pucCW)
{ 
	U8	cmd[100]	={0x80,0xEA,0x80,0x00};
	U8	cmd2[100]	={0x00,0x84,0x00,0x00,0x10};
	U8	response[50]={0};
	U16 cmdlen	=0;
	U16	resplen =0;
	U8  pbword[2]={0};
	Smart_ErrorCode_t bresult=SMC_NO_ERROR;
	int i = 0;
	U8  tempcw[16] = {0};

	memcpy(cmd+4,buf+4,0x43);

	cmd[4+0x43]		= 0x01;
	cmd[4+0x43+1]	= 0x00;
	
	cmdlen			= 0x49;

	bresult=bjst_transfer(Handle,cmd,cmdlen,response,&resplen,pbword);

	if((bresult!=SMC_NO_ERROR)&&(resplen<17))
	{
		printf("传送数据发生错误!!!\n");
		return false;
	}
	else if ((response[0]==0x6B)&&(response[1]==0x01))
	{
		printf("没有授权\n");
		return false;
	}

	for (i=0; i<16; i++)
	{
		tempcw[i] = response[i+1]^keywords[i%8];
	}
	
	memcpy(pucCW,tempcw,16);

	return true;
}


/************************************************************************/
/* 处理EMM,主要就是完成对卡授权了。收取EMM的时候设置filter的第一个字节0x82,
5,6,7,8个字节就是卡号了。可以仅设置第一个字节,多收几个EMM研究研究哦! 

   输入     Handle -- smart card 句柄  data -- EMM信息,len -- 数据长度
   输出     无
   返回值   true -- 解析EMM成功 false --解析EMM失败
   其他                                                                   */
/************************************************************************/

bool bjst_parse_emm(Smart_Handle_t Handle,U8* data,U16 len)
{
	U8  cmd1[100]={0};
	U8  cmd2[10]={0x00,0xc0,0x00,0x00};
	U8	reponse[100];
	U16 writelen = 0;
	U16	replen=0;
	U8  status[2];

	writelen = data[15]+5;
	memcpy(cmd1,data+11,writelen);
	bjst_transfer(Handle,cmd1,writelen,reponse,&replen,status);
	
	if (replen > 2)
	{
		return true;
		
	}else
	{
		return false;
	}

	return true;
}

/************************************************************************/
/* 数据传输,机顶盒和智能卡通讯的接口,其实也可以不用封装,直接调用Smart_Transfer,
在这主要是加打印调试用的

   输入     Handle -- smart card 句柄,ins -- 要传送的数据,NumberToWrite -- 
 要传送的数据长度
   输出     Response -- 回应数据, Read -- 回应的数据长度,Status -- 状态字节 
   返回值   数据传输错误类型 SMC_NO_ERROR表示无错误
   其他            
                                                                        */
/************************************************************************/

static Smart_ErrorCode_t bjst_transfer(Smart_Handle_t Handle,
								    U8*			 ins,
								    U16			 NumberToWrite,
								    U8*			 Response,
								    U16*		 Read,
								    U8*			 Status)
{
	Smart_ErrorCode_t error = SMC_NO_ERROR;

	U8 tempins[256] = {0x42,0x4a,0x53,0x54};

	memcpy(tempins+4, ins, NumberToWrite);
	
	error = Smart_Transfer(Handle,tempins,NumberToWrite,Response,0,Read,Status);

//	printf("Status[0]=0x%02x   Status[1]=0x%02x error = %d\n",Status[0],Status[1],error);
	return error;
}


/////////////////////----The end ----------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -