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

📄 at1608.c

📁 插入式IC卡1608驱动
💻 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 + -