📄 at1608.c
字号:
#define IN_AT1608
#include "..\includes.h"
uint8 const passwordr[3]={0x19,0x99,0x04};
uchar const passwordw[3]={0x4B,0X59,0X48};
uchar GC[8];
uchar Crypto[8];
uchar R[7];
uchar S[7];
uchar Q0[8];
uchar Q1[8];
uchar Q2[8];
uchar T[7];
//uchar PAC=0;
/********************************************************************************************
** ic is the initial
** 上电IC卡复位。
*********************************************************************************************/
void Initial_Iccard(void)
{
P5DIR |= CARD_RST+CARD_SCL+CARD_DATA;
P2IFG = 0;
P2IES = CARD_CHECK; // 下降沿触发中断
P2IE = CARD_CHECK; // 允许卡中断 p1。0
P1IFG =0;
P1IES = BIT0+BIT1;
P1IE = BIT0+BIT1;
P5OUT |= CARD_RST+CARD_SCL+CARD_DATA;
}
void delay1(uint16 ti)
{
uint16 i;
for(i=0;i<ti;i++)
I2C_delay();
}
void ic_reset(void)
{
SCL_0;
I2C_delay(); I2C_delay();
IC_RESET0;
I2C_delay(); I2C_delay();
IC_RESET1;
I2C_delay(); I2C_delay();
SCL_1;
I2C_delay(); I2C_delay();
SCL_0;
I2C_delay(); I2C_delay();
IC_RESET0;
I2C_delay(); I2C_delay();
}
/******************************************************************************
** 首先复位,其次读数据(SDA—OUT),验证卡是否正确
**
** 检验该卡是不是1608卡,0x2c,0xaa,0x55,0xa0是证明该卡的口令是否正确
*******************************************************************************/
uint8 read_reset(void) //to the IC card
{
uchar i,j;
uint8 rFlag=0;
uint8 common[4];
ic_reset();
SDA_IN;
for(j=0;j<4;j++)
{
for(i=0;i<8;i++)
{
SCL_0;
I2C_delay();
common[j]=(common[j]>>1);
if(SDA_VALUE == 1)
common[j] |= 0x80;
SCL_1;
I2C_delay();
}
}
SCL_0;
I2C_delay();
SDA_OUT;
SDA_1;
I2C_delay();
if((common[0]==0x2c)&&(common[1]==0xaa)&&(common[2]==0x55)&&(common[3]==0xa0))
rFlag=1;
return(rFlag);
}
/***********************************************************************************
//the following is begin to write/read byte
************************************************************************************/
/************************************************************************************************************
**开始I2C,写卡命令和地址
**add:写命令 abyte:卡地址
************************************************************************************************************/
uint8 w_add_byte(uchar Add,uchar Abyte)//include the start single
{
I2C_delay();
stop_i2c();
start_i2c();
outbyt(Add);
if(wait_ack())
{
outbyt(Abyte);
return(wait_ack());
}
else
return 0;
}
/***************************************************************************************************
** return a bit in order to informat us the read is right or wrong
** chang the addre we can read the configuration(0XBB5) and the user(0XB1)
** local:存放所读出内容 adddre 写命令 abyte:卡地址 length:读出的长度
***************************************************************************************************/
uint8 read_con_use(uchar *local,uchar addre,uchar abyte,uchar length)
{
uchar i;
i=0;
if(w_add_byte(addre,abyte)) //最后应答信号变为SDA—OUT
{
SDA_IN; //读取时变为输入SDA—IN
for(i=0;i<length-1;i++)
{
*(local+i)=inbyt();
ack();
}
*(local+i) = inbyt();
nack();
stop_i2c();
Nnop();
return(1);
}
else
{
stop_i2c();
Nnop();
return(0);
}
}
uint8 readarry(uchar *point,uchar add,uchar abyte,uchar len)
{
uchar i;
uint8 icFlag=0;
for(i=0;i<COUNT;i++)
{
if(read_con_use(point,add,abyte,len))
{
icFlag=1;
break;
}
}
return(icFlag);
}
uint8 writearry(uchar *point,uchar add,uchar abyte,uchar len)
{
uchar i;
uint8 iFlag=0;
for(i=0;i<COUNT;i++)
{
if(write_con_use(point,add,abyte,len))
{
iFlag=1;
break;
}
else
iFlag=0;
}
return(iFlag);
}
/********************************************************************************
**the following is begin to authenticate
**读熔丝
*******************************************************************************/
uint8 read_fuse()
{
uint8 cFlag=0;
if(w_add_byte(R_CON,0X80))
{
SDA_IN;
if(inbyt()==0x00)
cFlag=1;
}
//nack();
stop_i2c();
return (cFlag);
}
uint8 ver_pass(void)
{
uint8 bFlag=0,PAC=0;
if(writearry((uint8*)passwordr,V_PASS,0X0f,3)) //verify read password;
{
if(w_add_byte(R_CON,0X7c))
{
SDA_IN;
PAC=inbyt();
stop_i2c();
if(PAC==0XFF)
bFlag=1;
}
}
if(bFlag==1)
{
bFlag=0;
if(writearry((uint8*)passwordw,V_PASS,0X07,3)) //verify write password;
{
if(w_add_byte(R_CON,0X78))
{
SDA_IN;
PAC=inbyt();
//nack();
stop_i2c();
if(PAC==0XFF)
bFlag=1;
}
}
}
return(bFlag);
}
uint8 befor_F1(void)
{
uint8 f1flag=0;
if(readarry(GC,R_CON,0X20,0x08)) //Read AAC and NC
{
if(readarry(Crypto,R_CON,0X28,0x08)) //Read CI
f1flag=1;
}
return(f1flag);
}
uint8 befor_auth(void)
{
uchar i;
uint8 auFlag=0;
uint8 common[8];
read_reset();
if(read_reset()) //it showes the card is 1608 type
{
if(readarry(common,R_CON,0X0C,4)) // whether the common="HYKJ"
{
if((common[0]==0X48)&&(common[1]==0X59)&&(common[2]==0X4B)&&(common[3]==0X4A))
{
if(read_fuse()) //whether the fuse is blown
{
if(readarry(common,R_CON,0X10,8)) //judge the AR0~AR7?=0X1F
{
for(i=0;i<8;i++)
{
if(common[i]!=0X1F)
{
//auFlag=0;
break;
}
else
auFlag=1;
}
if(auFlag==1)
{
auFlag = 0;
if(befor_F1()) //request to get to GC CI;
auFlag=1;
}
}
}
}
}
}
return(auFlag);
}
/******************************************************************************************
**写卡操作
**buff:待写内容指针 addre写命令 abyte:待写卡地址 length:写长度
*********************************************************************************************/
uint8 write_con_use(uchar *buff,uchar addre,uchar abyte,uchar length)
{
uchar i,k;
uint8 bFlag;
bFlag=0;
k=0;
loop: if(w_add_byte(addre,abyte)) //卡起始信号 写命令和地址
{
for(i=k;i<length;i++)
{
outbyt(*(buff+i));
abyte += 1;
if(!wait_ack())
break;
else if(i == length-1)
bFlag = 1;
if(abyte%16 == 0 && i!=length-1) //判断是否超过页写16字节
{
k = i+1;
stop_i2c();OSTimeDly(2);
goto loop;
}
}
}
stop_i2c();
OSTimeDly(2);
return(bFlag);
}
/******************************************************************************
****** begin to authentication
******************************************************************************/
uint8 F1auth(void)
{
uchar i;
uint8 gcFlag=0;
uchar KS[8]={"fieldbyn"} ;
if(befor_auth())//read the AAC and NC
{
GC[0]=0X31;
for(i=0;i<8;i++) //get to the GC
GC[i]^=KS[i];
i=GC[0];
GC[0]=GC[7];
GC[7]=i;
i=GC[1];
GC[1]=GC[5];
GC[5]=i;
i=GC[2];
GC[2]=GC[4];
GC[4]=i;
i=GC[3];
GC[3]=GC[6];
GC[6]=i;
gcFlag=1;
}
return(gcFlag);
}
/****************************************************************************
**** The following is F2 authentication
*****************************************************************************/
void setINIT(void)
{
uchar i;
for(i=0;i<8;i++)
{
R[i] = 0;
S[i] = 0;
if(i<6) //modify at 04.1.17
Q0[i]=Read_Time[i];
else
Q0[i]=0x68;
}
for(i=0;i<5;i++)
T[i]=0;
}
void calculState(uchar Ri, uchar Ti, uchar Si)
{
uchar temp,bit0;
bit0 = (R[6] >> 4) & 1;
temp = (2*R[6] | bit0) & 0x1F;
R[6] = R[5];
R[5] = R[4];
R[4] = R[3];
R[3] = R[2] ^ Ri;
R[2] = R[1];
R[1] = R[0];
R[0] = (R[4] + temp);
if ( R[0] > 31 )
{
R[0] %= 31;
if ( R[0] == 0 ) R[0] = 31;
}
bit0 = ((S[6]>>6)&1);
temp = ((2*S[6])|bit0) & 0x7F;
S[6] = S[5];
S[5] = S[4] ^ Si;
S[4] = S[3];
S[3] = S[2];
S[2] = S[1];
S[1] = S[0];
S[0] = (S[6] + temp) ;
if ( S[0] > 127 )
{
S[0] %= 127;
if ( S[0] == 0 ) S[0] = 127;
}
temp = T[4];
T[4] = T[3];
T[3] = T[2];
T[2] = T[1] ^ Ti;
T[1] = T[0];
T[0] = (T[3] + temp);
if ( T[0] > 31 )
{
T[0] %= 31;
if ( T[0] == 0 ) T[0] = 31;
}
}
void calculKey(uchar key)
{
uchar Ri,Ti,Si;
Ri = key & 0x1F;
Si = ((key << 3) & 0x78) + ((key >> 5) & 0x07);
Ti = (key >> 3) & 0x1F;
calculState(Ri,Ti,Si);
}
uchar calculv(void)
{
uchar Ri,Ti,Si_,Si;
uchar lastCalc = 0;
calculState(0,0,0);
Ri = (R[0] ^ R[4]) & 0x1F;
Ti = (T[0] ^ T[3]) & 0x1F;
Si = S[0];
Si_= ~S[0];
lastCalc = ( (Ri & Si_) | (Si & Ti) ) & 0xF;
return lastCalc;
}
uchar calcul(uchar nbre)
{
uchar i;
uchar calc;
for (i=0;i<nbre;i++)
{
calc = calculv();
}
return calc;
}
void Authenticate(void)
{
uchar i;
for (i=0;i<4;i++)
{
calculKey(Crypto[2*i]); //crypto[] 为存放ci初始化前可写一随机数,认证卡时使用,每次认证会被自动改写。
calculKey(Crypto[2*i+1]);
calculKey(Q0[i]);
}
for (i=0;i<4;i++)
{
calculKey(GC[2*i]);
calculKey(GC[2*i+1]);
calculKey(Q0[i+4]);
}
for (i=0;i<8;i++)
{
Q2[i] = calcul(2);
Q2[i] <<= 4;
Q2[i] |= calcul(2);
Q1[i] = calcul(2);
Q1[i] <<= 4;
Q1[i] |= calcul(2);
}
}
/******************************************************************************
** transmit the Q0 and Q1 to the card
** 密码验证
******************************************************************************/
uint8 pass_Q(uchar add,uchar *buff)
{
uchar i;
uint8 q1Flag=0;
I2C_delay();
stop_i2c();
start_i2c();
outbyt(add);
if(wait_ack())
{
for(i=0;i<8;i++)
{
outbyt(*(buff+i));
if(!wait_ack())
break;
else if(i==7)
q1Flag=1;
}
}
stop_i2c();
delay1(100);
return(q1Flag);
}
uint8 reread_aac(void) //read one byte should no ack
{
uint8 ciFlag=0;
if(w_add_byte(R_CON,0X20))
{
SDA_IN;
if(inbyt()==0xff) //wait a minute.............
ciFlag=1;
}
nack();
stop_i2c();
return(ciFlag);
}
uint8 reread_ci(void)
{
uchar i;
uint8 Flagci=0;
if(readarry(Q0,R_CON,0X28,8))
{
for(i=0;i<8;i++)
{
if(Q0[i]==Q2[i])
Flagci=1;
else
{
Flagci=0;
break;
}
}
}
return(Flagci);
}
uint8 verify_auth(void)
{
uint8 auFlag=0;
if(pass_Q(I_AUTH,Q0)) //pass Q0
{
if(pass_Q(V_AUTH,Q1)) //pass Q1
{
if(reread_aac()) //Reread AAC and CI
{
if(reread_ci())
auFlag=1;
}
}
}
return(auFlag);
}
uint8 F2authen(void)
{
setINIT();
Authenticate();
if(verify_auth())
return(1);
else
return(0);
}
//the following is user zones
uint8 set_zone(uchar Zone)
{
uchar zFlag=0;
if(w_add_byte(S_USER,Zone))
zFlag=1;
stop_i2c();
delay1(100);
return(zFlag);
}
/********************************************************************
****zon:0~7 user zones; plac1:the place that reading *
* *
*********************************************************************/
uint8 access(uchar zon,uchar *place1,uchar add,uchar byteb,uchar length)
{
uint8 acFlag=0;
if(set_zone(zon))
{
if(readarry(place1,add,byteb,length))
acFlag=1;
}
return acFlag;
}
/*************************************************************************************************
//判断是否通过认证(1608卡)
**************************************************************************************************/
uint8 Verify_1608(void)
{
uint8 RightFlag = 0;
if(F1auth()) //是否1608卡
{
if(F2authen())
{
if(ver_pass()) //校验密码
RightFlag =1;
}
}
return RightFlag;
}
/****************************************************************************
the end
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -