?? bjst.c
字號:
/*
本代碼僅作為學(xué)習(xí)研究之目的使用,請您于24小時內(nèi)自覺將其刪除,請勿應(yīng)用于商業(yè)活動或其它贏利性活動中,
否則后果自負!
*/
/******************************************************
* 文件名: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);//數(shù)據(jù)傳輸
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解密
/************************************************************************/
/* 初始化, 主要工作是讀取卡內(nèi)的基本信息,如卡號、運營商等信息
輸入 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 后必須首先執(zhí)行,之后才可以執(zhí)行其他的命令
輸入 Handle -- smart card 句柄
輸出 無
返回值 true -- 命令執(zhí)行成功 false -- 命令執(zhí)行失敗
其他
*/
/************************************************************************/
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卡片上顯示的數(shù)字,也用來做授權(quán)尋址
輸入 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("數(shù)據(jù)錯誤 \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傳給機頂盒的時候就是用
這組數(shù)做的加密(雖然算法比較簡單,但是至少是有這個意識的,所以很鄙視tf和sm的
做法,還到處宣揚什么安全性,無語...),其實當時弄這個地方還是花費了不少時間的!
輸入 Handle -- smart card 句柄
輸出 無
返回值 true -- 讀取數(shù)據(jù)成功 false -- 讀取數(shù)據(jù)失敗
其他 得到的信息存儲于全局變量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("數(shù)據(jù)錯誤 \n");
return false;
}
memcpy(keywords, response, 8);
return true;
}
/************************************************************************/
/* 處理解析ECM,得到CW,得到它我們就可以看節(jié)目了!收取ECM的時候設(shè)置filter
的第一個字節(jié)0x80/0x81就ok了
輸入 Handle -- smart card 句柄 buf -- ECM信息,從0x80/0x81開始
輸出 pucCW -- 就是cw啦,16個字節(jié),不是奇偶,就是奇偶,根據(jù)情況你自己試驗
返回值 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("傳送數(shù)據(jù)發(fā)生錯誤!!!\n");
return false;
}
else if ((response[0]==0x6B)&&(response[1]==0x01))
{
printf("沒有授權(quán)\n");
return false;
}
for (i=0; i<16; i++)
{
tempcw[i] = response[i+1]^keywords[i%8];
}
memcpy(pucCW,tempcw,16);
return true;
}
/************************************************************************/
/* 處理EMM,主要就是完成對卡授權(quán)了。收取EMM的時候設(shè)置filter的第一個字節(jié)0x82,
5,6,7,8個字節(jié)就是卡號了。可以僅設(shè)置第一個字節(jié),多收幾個EMM研究研究哦!
輸入 Handle -- smart card 句柄 data -- EMM信息,len -- 數(shù)據(jù)長度
輸出 無
返回值 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;
}
/************************************************************************/
/* 數(shù)據(jù)傳輸,機頂盒和智能卡通訊的接口,其實也可以不用封裝,直接調(diào)用Smart_Transfer,
在這主要是加打印調(diào)試用的
輸入 Handle -- smart card 句柄,ins -- 要傳送的數(shù)據(jù),NumberToWrite --
要傳送的數(shù)據(jù)長度
輸出 Response -- 回應(yīng)數(shù)據(jù), Read -- 回應(yīng)的數(shù)據(jù)長度,Status -- 狀態(tài)字節(jié)
返回值 數(shù)據(jù)傳輸錯誤類型 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 ----------------
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -