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

📄 cardlib.c

📁 cpu卡驱动源程序,根据需要可自行修改 cpu卡驱动源程序,根据需要可自行修改
💻 C
📖 第 1 页 / 共 3 页
字号:
/*----------------------------------------------------------------------
  按《IC卡规范》定义的IC卡库函数
  Copyright (c) 2003 by laohui(2003/3/26--2003/4/1)
----------------------------------------------------------------------*/

#include <string.h>
#include <stdio.h>
#include "taxtype.h"

#include "smart.h"

#define GB_20050729_SMART_UPDATE	//读CPU卡修改

//定义CPU卡读写所需的全局变量
struct APDU_COMM apdu_comm;
struct APDU_RESP apdu_resp;

extern uchar UC_card_location;//选择卡的位置

uchar IC_select_file(uchar mode,uchar *file,uchar *id,uchar *len,uchar *fci,uint *status);
uchar IC_read_binary(uchar mode,uchar id,uint offset,uchar *len,uchar *binary,uint *status);
uchar IC_read_record(uchar mode,uchar id,uchar no,uchar *len,uchar *record,uint *status);
//uchar IC_append_record(uchar mode,uchar id,uchar level,uchar len,uchar *record,uint *status);
uchar IC_update_binary(uchar mode,uchar id,uchar level,uchar len,uchar *binary,uint offset,uint *status);//#ifdef GB_20050729_SMART_UPDATE
uchar IC_update_record(uchar mode,uchar id,uchar level,uchar len,uchar *record,uchar no,uint *status);
uchar IC_verify(uchar id,uchar len,uchar *pin,uint *status);
uchar IC_get_challenge(uchar kind,uchar *len,uchar *random,uint *status);
uchar IC_external_authentication(uchar id,uchar *encrypt,uint *status);
uchar IC_internal_authentication(uchar id,uchar *source,uchar *len,uchar *encrypt,uint *status);
uchar TSAM_get_register_nb(uchar *len,uchar *reg,uint *status);
uchar TSAM_terminal_register(uchar *mac2,uchar *len,uchar *pin,uint *status);
uchar TSAM_issue_invoice(uchar *invoice,uchar *len,uchar *control_code,uint *status);
uchar TSAM_declare_duty(uchar *declare,uchar *len,uchar *sign,uint *status);
uchar TSAM_update_controls(uchar *controls,uint *status);
uchar TSAM_input_invoice_nb(uchar *input,uint *status);
uchar TSAM_verify_fiscal_pin(uchar *pin,uchar *len,uchar *new_pin,uint *status);
uchar TSAM_daily_collect_sign(uchar sign_type,uchar *sign_data,uchar *len,uchar *signed_data,uint *status);
uchar TID_register_sign(uchar *sign,uchar *len,uchar *mac2,uint *status);
uchar TID_data_collect(uchar *collect,uint *status);
uchar TID_distribute_invoice_nb(uchar *len,uchar *distribute,uint *status);

//基本
/*----------------------------------------
功能:
	选择所要进行操作的文件
输入:
	mode 选择文件方式
		0 文件标识符方式
		1 文件名方式
	file 要选择的文件名
	id 要选择的文件标识
	len 选择DDF或ADF文件时返回的文件控制信息FCI的长度指针
	fci 选择DDF或ADF文件时返回的文件控制信息FCI指针
	status 状态字指针
输出:
	0 成功
	1 操作完成,返回状态字不对
	0xd3 接收数据超时出错
	0xd6 奇偶校验出错
	0xd9 通信出错
	0xc2 该卡是另类CPU卡
	len 选择DDF或ADF文件时返回的文件控制信息FCI的长度
	fci 选择DDF或ADF文件时返回的文件控制信息FCI
	status 状态字
------------------------------------------*/
uchar IC_select_file(uchar mode,uchar *file,uchar *id,uchar *len,uchar *fci,uint *status)
{
	uchar i,rn;

	apdu_resp.status = 0xffff;

    apdu_comm.command[0]=0;
    apdu_comm.command[1]=0xa4;
	if(mode==0)
	{
	    apdu_comm.command[2]=0;
	    apdu_comm.command[3]=0;
		apdu_comm.lc=0x02;
	    apdu_comm.in_data=id;
	}
	else 
	{
	    apdu_comm.command[2]=0x04;
	    apdu_comm.command[3]=0;
		apdu_comm.lc=strlen(file);
	    apdu_comm.in_data=file;
	}
	apdu_comm.le=0;
	apdu_resp.out_data=fci;

	for(i=0;i<3;i++)
	{
		rn=smart_card_apdu(UC_card_location,&apdu_comm,&apdu_resp);
		*status=apdu_resp.status;
		if(rn==0)
		{
			*len=apdu_resp.out_len;
			if ( apdu_resp.status == 0x9000 ) return 0;
			else return 1;
		}
		else 
		{
			if(rn==0xc2) return rn;
		}
	}
	return rn;
}

/*-------------------------------------------------------------
功能:
	读取二进制文件的内容或部分内容
输入:
	mode 选择文件方式
		0 文件标识符方式
		1 选择当前文件
	id 当 mode=0 时有效,为要选择的文件标识
	offset 读的偏移量
		当 mode=0 偏移量最大不超过0xff
		当 mode=1 偏移量最大不超过0x7fff
	len 读取的字节数
	binary 读出内容的指针
	status 状态字指针
输出:
	0 成功
	1 操作完成,返回状态字不对
	0xd3 接收数据超时出错
	0xd6 奇偶校验出错
	0xd9 通信出错
	0xc2 该卡是另类CPU卡
	len 实际读取的字节数
	binary 读取的内容
	status 状态字
-----------------------------------------------------------------*/
uchar IC_read_binary(uchar mode,uchar id,uint offset,uchar *len,uchar *binary,uint *status)
{
	uchar i,rn;

	apdu_resp.status = 0;

    apdu_comm.command[0]=0;
    apdu_comm.command[1]=0xb0;
	if(mode==0)
	{
	    apdu_comm.command[2]=id+0x80;
	    apdu_comm.command[3]=(uchar)offset;
	}
	else 
	{
	    apdu_comm.command[2]=(uchar)((offset>>8)&0x7f);
	    apdu_comm.command[3]=(uchar)offset;
	}
	apdu_comm.lc=0;
	apdu_comm.le=*len;
	apdu_resp.out_data=binary;

	for(i=0;i<3;i++)
	{
		rn=smart_card_apdu(UC_card_location,&apdu_comm,&apdu_resp);
		*status=apdu_resp.status;
		if(rn==0)
		{
			*len=apdu_resp.out_len;
			if ( apdu_resp.status == 0x9000 ) return 0;
			else return 1;
		}
		else 
		{
			if(rn==0xc2) return rn;
		}
	}
	return rn;
}

/*-------------------------------------------------------------
功能:
	读取记录文件的内容
输入:
	mode 选择文件方式
		0 文件标识符方式
		1 选择当前文件
	id 当 mode=0 时有效,为要选择的文件标识
	no 读的记录号
		如果有N个记录,no可取1到N
	len 读取的数据长度
	record 读取记录的指针
	status 状态字指针
输出:
	0 成功
	1 操作完成,返回状态字不对
	0xd3 接收数据超时出错
	0xd6 奇偶校验出错
	0xd9 通信出错
	0xc2 该卡是另类CPU卡
	len 实际读取的数据长度
	record 读取的记录
	status 状态字
-----------------------------------------------------------------*/
uchar IC_read_record(uchar mode,uchar id,uchar no,uchar *len,uchar *record,uint *status)
{
	uchar i,rn;

	apdu_resp.status = 0;

    apdu_comm.command[0]=0;
    apdu_comm.command[1]=0xb2;
	apdu_comm.command[2]=no;
	if(mode==0) apdu_comm.command[3]=(id<<3)+0x04;
	else apdu_comm.command[3]=0x04;
	apdu_comm.lc=0;
	apdu_comm.le=*len;
	apdu_resp.out_data=record;

	for(i=0;i<3;i++)
	{
		rn=smart_card_apdu(UC_card_location,&apdu_comm,&apdu_resp);
		*status=apdu_resp.status;
		if(rn==0)
		{
			*len=apdu_resp.out_len;
			if ( apdu_resp.status == 0x9000 ) return 0;
			else return 1;
		}
		else 
		{
			if(rn==0xc2) return rn;
		}
	}
	return rn;
}

/*-------------------------------------------------------------
功能:
	用于对变长记录文件和循环记录文件追加记录(这里不用)
输入:
	mode 选择文件方式
		0 文件标识符方式
		1 选择当前文件
	id 当 mode=0 时有效,为要选择的文件标识
	level 安全级别
		0 无保护
		1 线路保护
		2 线路加密保护
	len 记录长度
		如果有线路保护或线路加密保护,len为最终数据的长度
	record 所要追加的新记录
		如果为线路保护或线路加密保护,record为最终数据内容
	status 状态字指针
输出:
	0 成功
	1 操作完成,返回状态字不对
	0xd3 接收数据超时出错
	0xd6 奇偶校验出错
	0xd9 通信出错
	0xc2 该卡是另类CPU卡
	status 状态字
-----------------------------------------------------------------*/
//uchar IC_append_record(uchar mode,uchar id,uchar level,uchar len,uchar *record,uint *status)
//{
//	uchar i,rn;
//
//	apdu_resp.status = 0;
//
//	if(level==0) apdu_comm.command[0]=0;
//	else apdu_comm.command[0]=0x04;
//    apdu_comm.command[1]=0xe2;
//	apdu_comm.command[2]=0;
//	if(mode==0) apdu_comm.command[3]=id<<3;
//	else apdu_comm.command[3]=0;
//	apdu_comm.lc=len;
//	apdu_comm.in_data=record;
//	apdu_comm.le=0;
//
//	for(i=0;i<3;i++)
//	{
//		rn=smart_card_apdu(UC_card_location,&apdu_comm,&apdu_resp);
//		*status=apdu_resp.status;
//		if(rn==0)
//		{
//			if ( apdu_resp.status == 0x9000 ) return 0;
//			else return 1;
//		}
//		else 
//		{
//			if(rn==0xc2) return rn;
//		}
//	}
//	return rn;
//}

//#ifdef GB_20050729_SMART_UPDATE
/*-------------------------------------------------------------
功能:
	用于写二进制文件
输入:
	mode 选择文件方式
		0 文件标识符方式
		1 选择当前文件
	id 当 mode=0 时有效,为要选择的文件标识
	level 安全级别
		0 无保护
		1 线路保护
		2 线路加密保护
	len 数据长度
		如果有线路保护或线路加密保护,len为最终数据的长度
	len 读取的字节数
	binary 所要更新的数据
		如果为线路保护或线路加密保护,binary为最终数据内容
	offset 写的偏移量
		当 mode=0 偏移量最大不超过0xff
		当 mode=1 偏移量最大不超过0x7fff
	status 状态字指针
输出:
	0 成功
	1 操作完成,返回状态字不对
	0xd3 接收数据超时出错
	0xd6 奇偶校验出错
	0xd9 通信出错
	0xc2 该卡是另类CPU卡
	status 状态字
-----------------------------------------------------------------*/
uchar IC_update_binary(uchar mode,uchar id,uchar level,uchar len,uchar *binary,uint offset,uint *status)
{
	uchar i,rn;

	apdu_resp.status = 0;

	if(level==0) apdu_comm.command[0]=0;
	else apdu_comm.command[0]=0x04;
    apdu_comm.command[1]=0xd6;
	if(mode==0)
	{
	    apdu_comm.command[2]=id+0x80;
	    apdu_comm.command[3]=(uchar)offset;
	}
	else 
	{
	    apdu_comm.command[2]=(uchar)((offset>>8)&0x7f);
	    apdu_comm.command[3]=(uchar)offset;
	}
    
	apdu_comm.lc=len;
	apdu_comm.in_data=binary;
	apdu_comm.le=0;

	for(i=0;i<3;i++)
	{
		rn=smart_card_apdu(UC_card_location,&apdu_comm,&apdu_resp);
		*status=apdu_resp.status;
		if(rn==0)
		{
			if ( apdu_resp.status == 0x9000 ) return 0;
			else return 1;
		}
		else 
		{
			if(rn==0xc2) return rn;
		}
	}
	return rn;
}
//#endif

/*-------------------------------------------------------------
功能:
	用于更新定长记录和变长记录文件
输入:
	mode 选择文件方式
		0 文件标识符方式
		1 选择当前文件
	id 当 mode=0 时有效,为要选择的文件标识
	level 安全级别
		0 无保护
		1 线路保护
		2 线路加密保护
	len 记录长度
		如果有线路保护或线路加密保护,len为最终数据的长度
	record 所要更新的新记录
		如果为线路保护或线路加密保护,record为最终数据内容
	no 更新的记录号
	status 状态字指针
输出:
	0 成功
	1 操作完成,返回状态字不对
	0xd3 接收数据超时出错
	0xd6 奇偶校验出错
	0xd9 通信出错
	0xc2 该卡是另类CPU卡
	status 状态字
-----------------------------------------------------------------*/
uchar IC_update_record(uchar mode,uchar id,uchar level,uchar len,uchar *record,uchar no,uint *status)
{
	uchar i,rn;

	apdu_resp.status = 0;

	if(level==0) apdu_comm.command[0]=0;
	else apdu_comm.command[0]=0x04;
    apdu_comm.command[1]=0xdc;
	apdu_comm.command[2]=no;
	if(mode==0) apdu_comm.command[3]=(id<<3)+0x04;

⌨️ 快捷键说明

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