📄 cardlib.c
字号:
/*----------------------------------------------------------------------
按《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 + -