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

📄 fenxi_tpdu_t0_v2.cpp

📁 分析机顶盒与智能卡通信的串口数据解析TPDU
💻 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 + -