📄 fenxi_tpdu_t0_v2.cpp
字号:
/*********************************分析机顶盒与智能卡通信的串口数据解析TPDU*******************************/
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
/*********************************错误码定义*******************************/
#define SUCCESS 0x00
#define ERR_GET_TPDU 0x01
#define ERR_GET_SW1 0x02
#define ERR_GET_SW2 0x03
#define ERR_GET_GTR 0x04
#define ERR_CHK_GTR 0x05
#define ERR_SEND_TPDU_AGAIN 0x06
#define ERR_CHK_TPDU_AGAIN 0x07
#define ERR_SW1_SW2 0x08
#define ERR_READ_BYTES 0x09
#define ERR_UNKNOWN_9XXX 0x0A
#define ERR_UNKNOWN_90XX 0x0B
#define ERR_UNKNOWN_6XXX 0x0C
#define ERR_NOT_6X_OR_9X 0x0D
#define ERR_SEND_BYTES 0x0E
#define ERR_TS 0x7F
#define ERR_T0 0x80
#define ERR_TA1 0x81
#define ERR_TA2 0x82
#define ERR_TA3 0x83
#define ERR_TB1 0x84
#define ERR_TB2 0x85
#define ERR_TB3 0x86
#define ERR_TC1 0x87
#define ERR_TC2 0x88
#define ERR_TC3 0x89
#define ERR_TD1 0x8A
#define ERR_TD2 0x8B
#define ERR_TD3 0x8C
#define ERR_HIS 0x8D
#define ERR_UNKNOWN_T_Type 0x8E
/**********************数据结构定义*******************************/
typedef unsigned char uchar;
typedef unsigned char SW;
typedef struct str_TPDU {
uchar CLA;
uchar INS;
uchar P1;
uchar P2;
uchar P3;
} TPDU;
typedef struct str_INPUTDATA
{
uchar len;
uchar buf[256];
} INPUTDATA;
typedef struct str_ATR {
uchar TS;
uchar T0;
uchar TA1, TA2, TA3;
uchar TB1, TB2, TB3;
uchar TC1, TC2, TC3;
uchar TD1, TD2, TD3;
uchar his[15];
// uchar TCK;
} ATR;
typedef enum en_Condition {
TYPE1=1, TYPE2, TYPE3, TYPE4
} e_Condition;
/**********************全局变量声明*******************************/
char strFileIn[256];
char strFileOut[256];
FILE *g_fpin;
FILE *g_fpout;
TPDU g_tpdu;
ATR g_atr;
INPUTDATA g_inputData;
SW g_sw1, g_sw2;
int g_last_errno;
int g_cnt_tpdu;
int g_apdu_cnt;
int g_not_done;
int g_Lc;
int g_Le;
int g_cond_type;
bool g_bshow = 0;
/**********************函数声明 *******************************/
int getATR(); //抓取一个ATR
void outputATR(); // 输出一个ATR
int mainProc(); //处理一个APDU命令响应对
bool getTPDU(void); // 抓取一个C-TPDU
bool getSW1(); // 抓取SW1
bool getSW2(); // 抓取SW2
bool readBytes(int num); //抓取入卡或出卡数据
void install(); //初始化函数
inline bool checkGTR() {return (g_tpdu.CLA==0x00 && g_tpdu.INS==0xC0 && g_tpdu.P1==0x00
&&g_tpdu.P2==0x00) ; } // 检查是否为Get Response 命令
inline bool checkSend_TPDU_Again(const TPDU &tmp)
{ return (tmp.CLA==g_tpdu.CLA && tmp.INS==g_tpdu.INS && tmp.P1==g_tpdu.P1
&& tmp.P2==g_tpdu.P2 && tmp.P3==g_sw2) ; } //检查重发命令
inline bool EQ(const uchar a, const uchar b) { return (a==b); } //判断两个一字节数是否相等
inline uchar High4(const uchar c) {return (c >> 4); } //返回高四位
inline uchar Low4(const uchar c) {return (c&0x0f); } // 返回第四位
inline bool isGetResponse() { return checkGTR(); } //判断是否为 Get Response 命令
bool findFirst9000()
{
while(true)
{
if(fscanf(g_fpin, "%x", &g_sw1) == EOF) return false;
if(EQ(g_sw1,0x90))
{
if(fscanf(g_fpin, "%x", &g_sw2) == EOF) return false;
if(EQ(g_sw2, 0x00)) break;
else fprintf(g_fpout, " %02X", g_sw2);
}
else fprintf(g_fpout, " %02X", g_sw1);
}
fprintf(g_fpout, "\nReturn code [SW1 SW2]:\n%02X %02X\n", g_sw1, g_sw2);
return true;
}
int main()
{
install();
//read input file
do
{
puts("Please input File Name:");
} while(gets(strFileIn)==NULL || strlen(strFileIn) == 0);
sprintf(strFileOut, "%s.out", strFileIn);
if(!(g_fpin=fopen(strFileIn, "r"))) puts("Open File to read error");
if(!(g_fpout=fopen(strFileOut, "w"))) puts("Open File to write error");
//set ATR times in apperence.
uchar ttt;
puts("ATR times:");
scanf("%d", &ttt);
if(ttt-- > 0 ) g_last_errno = getATR();
if(g_last_errno != SUCCESS) goto end;
// print ATR
outputATR();
fputs("\n--------Below Pakcet(Not Done):-------\n", g_fpout);
if(!findFirst9000()) goto end;
g_not_done++;
//T != 0
if(EQ(High4(g_atr.T0),0xE))// T = 1
{
// deal with T = 1 half work tansport protocal
puts("Deal with T = 1 half work tansport protocal");
g_last_errno = ERR_UNKNOWN_T_Type;
goto end;
}
// T = 0
while(true)
{
fprintf(stdout, "APDU %d\n", ++g_apdu_cnt);
g_last_errno = mainProc();
if(g_last_errno != ERR_GET_TPDU)
{
fprintf(g_fpout, "Return code [SW1 SW2]:\n%02X %02X\n", g_sw1, g_sw2);
}
else
{
fprintf(g_fpout, "EOF\n");
}
fprintf(g_fpout, "\n\n\n\n");
if(g_last_errno == ERR_READ_BYTES || g_last_errno == ERR_SEND_BYTES) break;
if(g_last_errno != SUCCESS && g_last_errno == ERR_GET_TPDU) break;
if(g_last_errno == ERR_NOT_6X_OR_9X)
{
g_not_done++;
fputs("\n--------Below Pakcet(Not Done):-------\n", g_fpout);
if(!findFirst9000()) goto end;
}
}
end:
//print last error
fprintf(g_fpout, "\nLast errno: %02X\n", g_last_errno);
fprintf(g_fpout, "\nTotal Done Packet: %d\nNot Done Packet: %d\n", g_apdu_cnt, g_not_done);
// close file
fclose(g_fpin);
fclose(g_fpout);
system("pause");
return true;
}
/***************************** function: install() ***********************************/
void install()
{
memset((ATR*)&g_atr, 0, sizeof(g_atr));
memset((TPDU*)&g_tpdu, 0, sizeof(g_tpdu));
memset((INPUTDATA*)&g_inputData, 0, sizeof(g_inputData));
g_apdu_cnt = 0;
memset(strFileIn, 0, sizeof(strFileIn));
memset(strFileOut, 0, sizeof(strFileOut));
g_fpin = stdin;
g_fpout = stdout;
g_sw1 = g_sw2 = 0;
g_last_errno = SUCCESS;
g_apdu_cnt = g_cnt_tpdu = 0;
g_Lc = g_Le = 0;
g_cond_type = 0;
g_not_done = 0;
}
/***************************** function: getATR() ***********************************/
int getATR()
{
//初始化g_atr为00
memset(&g_atr, 0, sizeof(g_atr));
// get TS
int ch = 0x00;
while(fscanf(g_fpin, "%X", &ch)!= EOF && ch!=0x3B && ch!=0x3F)
fprintf(g_fpout, " %02X", ch);
g_atr.TS = ch;
if(g_atr.TS!=0x3B && g_atr.TS!=0x3F) return ERR_TS;
// get T0
if(fscanf(g_fpin, "%X", &g_atr.T0) == EOF) return ERR_T0;
// get TA1--TD1
if(g_atr.T0&0x80 && fscanf(g_fpin, "%X", &g_atr.TA1) == EOF) return ERR_TA1;
if(g_atr.T0&0x40 && fscanf(g_fpin, "%X", &g_atr.TB1) == EOF) return ERR_TB1;
if(g_atr.T0&0x20 && fscanf(g_fpin, "%X", &g_atr.TC1) == EOF) return ERR_TC1;
if(g_atr.T0&0x10 && fscanf(g_fpin, "%X", &g_atr.TD1) == EOF) return ERR_TD1;
if(g_atr.TD1 == 0) goto readHistoryBytes;
// get TA2--TD2
if(g_atr.TD1&0x80 && fscanf(g_fpin, "%X", &g_atr.TA2) == EOF) return ERR_TA2;
if(g_atr.TD1&0x40 && fscanf(g_fpin, "%X", &g_atr.TB2) == EOF) return ERR_TB2;
if(g_atr.TD1&0x20 && fscanf(g_fpin, "%X", &g_atr.TC2) == EOF) return ERR_TC2;
if(g_atr.TD1&0x10 && fscanf(g_fpin, "%X", &g_atr.TD2) == EOF) return ERR_TD2;
if(g_atr.TD2 == 0) goto readHistoryBytes;
// get TA2--TD2
if(g_atr.TD2&0x80 && fscanf(g_fpin, "%X", &g_atr.TA3) == EOF) return ERR_TA3;
if(g_atr.TD2&0x40 && fscanf(g_fpin, "%X", &g_atr.TB3) == EOF) return ERR_TB3;
if(g_atr.TD2&0x20 && fscanf(g_fpin, "%X", &g_atr.TC3) == EOF) return ERR_TC3;
if(g_atr.TD2&0x10 && fscanf(g_fpin, "%X", &g_atr.TD3) == EOF) return ERR_TD3;
readHistoryBytes:
//read History Bytes
int g_TPDU_cnt = g_atr.T0&0x0f;
int i = 0;
while(i < g_TPDU_cnt && fscanf(g_fpin, "%X", &g_atr.his[i++])!=EOF) ;
if(i != g_TPDU_cnt ) return ERR_HIS;
return SUCCESS;
}
/***************************** function: outputATR() ***********************************/
void outputATR()
{
fprintf(g_fpout,"\n-----------------------ATR-------------------------\n");
fprintf(g_fpout,"TS:=%02X\n", g_atr.TS);
fprintf(g_fpout,"T0:=%02X\n", g_atr.T0);
if(g_atr.T0&0x80) fprintf(g_fpout,"TA1:=%02X\n", g_atr.TA1);
if(g_atr.T0&0x40) fprintf(g_fpout,"TB1:=%02X\n", g_atr.TB1);
if(g_atr.T0&0x20) fprintf(g_fpout,"TC1:=%02X\n", g_atr.TC1);
if(g_atr.T0&0x10) fprintf(g_fpout,"TD1:=%02X\n", g_atr.TD1);
if(g_atr.TD1&0x80) fprintf(g_fpout,"TA2:=%02X\n", g_atr.TA2);
if(g_atr.TD1&0x40) fprintf(g_fpout,"TB2:=%02X\n", g_atr.TB2);
if(g_atr.TD1&0x20) fprintf(g_fpout,"TC2:=%02X\n", g_atr.TC2);
if(g_atr.TD1&0x10) fprintf(g_fpout,"TD2:=%02X\n", g_atr.TD2);
if(g_atr.TD2&0x80) fprintf(g_fpout,"TA3:=%02X\n", g_atr.TA3);
if(g_atr.TD2&0x40) fprintf(g_fpout,"TB3:=%02X\n", g_atr.TB3);
if(g_atr.TD2&0x20) fprintf(g_fpout,"TC3:=%02X\n", g_atr.TC3);
if(g_atr.TD2&0x10) fprintf(g_fpout,"TD3:=%02X\n", g_atr.TD3);
int hisLen = g_atr.T0&0x0f;
int i=0;
fprintf(g_fpout,"History bytes:%02X\n", hisLen);
while(i < hisLen)
{
fprintf(g_fpout," %02X", g_atr.his[i++]);
}
fprintf(g_fpout,"\n\n\n\n");
//fprintf(g_fpout,"\nTCK:%02X\n", g_atr.TCK);
}
/************************* function: getTPDU() ******************************/
// from g_fpin read and deal then send the result to g_fpout
// return the error no.
//功能:从文件中读出C-TPDU and R-TPDU
bool getTPDU(void)
{
if(fscanf(g_fpin, "%X", &g_tpdu.CLA) == EOF) return false;
if(fscanf(g_fpin, "%X", &g_tpdu.INS) == EOF) return false;
if(fscanf(g_fpin, "%X", &g_tpdu.P1) == EOF) return false;
if(fscanf(g_fpin, "%X", &g_tpdu.P2) == EOF) return false;
if(fscanf(g_fpin, "%X", &g_tpdu.P3) == EOF) return false;
if(g_cnt_tpdu >= 1) fprintf(g_fpout, "Return code [SW1 SW2]:\n%02X %02X\n", g_sw1, g_sw2);
// print g_tpdu
fprintf(g_fpout, "TPDU Header [CLA INS P1 P2 P3]:\n");
fprintf(g_fpout, " %02X %02X %02X %02X %02X\n", g_tpdu.CLA, g_tpdu.INS, g_tpdu.P1, g_tpdu.P2, g_tpdu.P3);
++g_cnt_tpdu;
return true;
};
/************************* function: getSW1() ******************************/
//功能:从文件中读出SW1
bool getSW1()
{
if(fscanf(g_fpin, "%X", &g_sw1) == EOF) return false;
if(g_bshow) fprintf(g_fpout, "SW1: %02X\n", g_sw1); // print sw1;
return true;
}
/************************* function: getSW2() ******************************/
//功能:从文件中读出SW2, 类似 getSW2()
bool getSW2()
{
if(fscanf(g_fpin, "%X", &g_sw2) == EOF) return false;
if(g_bshow) fprintf(g_fpout, "SW2: %02X\n", g_sw2); // print sw2
return true;
}
/************************* function: getSW2() ******************************/
//功能:从文件中读出入卡或出卡数据
bool readBytes(int num)
{
g_inputData.len = num;
uchar i = 0;
while(i++ <num)
{
if(fscanf(g_fpin, "%X", &g_inputData.buf[i-1]) == EOF) return false;
}
// print data
for(i=0; i<g_inputData.len; i++)
{
fprintf(g_fpout, " %02X", g_inputData.buf[i]);
if((i+1)%16 == 0) fprintf(g_fpout, "\n");
}
fprintf(g_fpout, "\n");
return true;
}
/***************************主功能函数 mainProc()**********************************/
//功能:处理一个C-APDU和R-APDU对,实际处理的是一组经过映射的C-TPDU和R-TPDU对
int mainProc()
{
g_cnt_tpdu = 0; // set g_cnt_tpdu = 0
g_cond_type = 0; // set g_cnt_tpdu = 0
//send g_tpdu
fprintf(g_fpout, "------------APDU[No.%02d]--------------\n", g_apdu_cnt);
if(!getTPDU()) return ERR_GET_TPDU; // ++g_cnt_tpdu in function getTPDU()
rec_sw1:
//get sw1
if(!getSW1()) return ERR_GET_SW1;
// judge condtion type of P3 in APDU
g_Lc = 0; // set g_Lc = 0
if(EQ(g_cnt_tpdu, 1) && EQ(g_tpdu.P3, 0))
{
g_cond_type = 1|2; // type 1 or 2;
if(EQ(High4(g_sw1), 9)) g_cond_type = 1;
else g_cond_type = 2; // sw1=6x
}
if(EQ(g_cnt_tpdu, 1) && g_tpdu.P3 > 0)
{
g_cond_type = 3|4; // type 3 or 4
g_Lc = g_tpdu.P3; // set g_Lc only in first time
}
//judge sw1 == INS?
if(EQ(g_sw1, g_tpdu.INS))
{
// juge Lc == 0?
if(g_Lc == 0 || isGetResponse())
{
g_Le = g_tpdu.P3; // set Le = g_tpdu.P3
fprintf(g_fpout, "Incoming data (0 bytes):\n-\n"); // no out card data
//wait and read Le bytes data from ICC
fprintf(g_fpout, "Outgoing data (%02X bytes):\n", g_Le);
if(!readBytes(g_Le)) return ERR_READ_BYTES;
goto rec_sw1;
}
else
{
// send Lc bytes data to ICC and set lc = 0
fprintf(g_fpout, "Incoming data (%02X bytes):\n", g_Lc);
if(!readBytes(g_Lc)) return ERR_SEND_BYTES;
fprintf(g_fpout, "Outgoing data (%0 bytes):\n-\n"); // no in card data
g_Lc = 0; // set g_Lc = 0
goto rec_sw1;
}
}
else
{
//get sw2
if(!getSW2()) return ERR_GET_SW2;
// g_Le = g_sw2; // set Le
if(High4(g_sw1) == 6)
{
//judge sw1 == 60?
switch(Low4(g_sw1))
{
case 0x0:
goto rec_sw1;
break;
case 0x1:
//send "get response" cmd;
if(!getTPDU()) return ERR_GET_GTR;
// if(!checkGTR()) return ERR_CHK_GTR;
g_tpdu.P3 = g_sw2;
goto rec_sw1;
break;
case 0xc:
//send cmd agin with p3=sw2
TPDU old_TPDU;
old_TPDU = g_tpdu;
if(!getTPDU()) return ERR_SEND_TPDU_AGAIN;
// if(!checkSend_TPDU_Again(old_TPDU)) return ERR_CHK_TPDU_AGAIN;
g_tpdu.P3 = g_sw2;
goto rec_sw1;
break;
default:
fprintf(g_fpout, "\nSW1:%02X 的含义与应用无关\n", g_sw1);
return ERR_UNKNOWN_6XXX;
break;
}
}
if(High4(g_sw1) == 9)
{
switch(Low4(g_sw1))
{
case 0x0:
switch(g_sw2)
{
case 0x00:
return SUCCESS;
break;
default:
fprintf(g_fpout, "\nSW1:%02X, 其含义依赖于相关的应用\n", g_sw1);
system("pause");
return ERR_UNKNOWN_90XX;
break;
}
default:
fprintf(g_fpout, "\nSW1:%02X, 其含义依赖于相关的应用\n", g_sw1);
return ERR_UNKNOWN_9XXX;
break;
}
}
// otherwise not 6 or 9
fprintf(g_fpout, "\nSW1:%02X, not 6x or 9x\n", g_sw1);
return ERR_NOT_6X_OR_9X;
}
return SUCCESS; //may never come here
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -