📄 esam_function.c
字号:
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 取回ESAM卡反馈回的信息*/
Read_Esam(ReplyData,2);
/* 取回8字节密文,4字节MAC码,2字节状态域 */
j = ReplyData[1]; // 该字节指明ESAM返回加密数据与4字节MAC码总长度
State = Get_Response(ReplyData, j);
/* 如果取数据和MAC码成功则执行下列操作 */
if(State ==0x9000)
{
/* 首先分离出加密的数据 */
for(i=0; i<j-4; i++)
{
CipherText[i] = ReplyData[i];
}
if(Mode == DES8)
Des8(CipherText,Keys,PlainText,DE1,j/8);
else
Des16(CipherText,Keys,PlainText,DE1,j/8);
for(i=0; i<DataLen; i++) // 从解密后的数据中取出源数据
{
*OutputPtr++ = PlainText[1+i]; // 因为解密后的数据第一个字节表示数据长度,所以屏蔽掉
}
}
/* 返回状态字 */
return State;
}
/****************************************************************/
/* 函数名: Select_File() */
/* 功能: 选择文件 */
/* 参数: */
/* FileID-----2字节长度的文件标识符 */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Select_File(Uint16 FileID)
{
Uint16 i,State;
/* 清空命令缓冲区和接收返回信息的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 第一次发送选择文件的命令头,如果正确,应该返回0xA4 */
CommandLength = 5;
Command[0] = 0x00; // 填写命令报文的头域
Command[1] = 0xA4;
Command[2] = 0x00;
Command[3] = 0x00;
Command[4] = 0x02;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发选择文件命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 发送选择文件命令的命令头域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定选择文件操作是否正确 */
Read_Esam(ReplyData,1);
/* 第二次发送选择文件命令的数据域,如果正确,应该返回状态9000 */
CommandLength = 2;
Command[0] = (FileID&0xFF00)>>8; // 填写命令报文的数据域
Command[1] = FileID&0x00FF;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发送选择文件命令的数据域 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发选择文件命令的数据域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定选择文件操作是否正确 */
Read_Esam(ReplyData,2);
/* 获取状态字 */
State = (ReplyData[0]<<8)|ReplyData[1];
return State;
}
/****************************************************************/
/* 函数名: Get_Random() */
/* 功能: 向ESAM发取随机数命令,并取得8字节或4字节随机数 */
/* 参数: */
/* OutputPtr--指向存放返回随机数的数组的指针 */
/* Length-----随机数长度,16进制表示(0x08,或0x04) */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Get_Random(Uint16 *OutputPtr, Uint16 Length)
{
Uint16 i,State;
/* 初始化接收ESAM卡应答信号的数据结构,并清空命令缓冲区 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 填写取随机数的命令报文 */
CommandLength = 5;
Command[0] = 0x00;
Command[1] = 0x84;
Command[2] = 0x00;
Command[3] = 0x00;
Command[4] = Length;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发取随机数命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发取随机数命令 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收随机数 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 先清除接收缓冲区 */
i = UART_RGET(URRBR);
/* 取出ESAM反馈的命令报文中的第二个字节,丢弃 */
while(!UART_FGET(URLSR,DR));
i = UART_RGET(URRBR);
/* 读返回的随机数信号 */
if(Length==0x08) // 如果是取8字节随机数
{
Read_Esam(ReplyData,10);
/* 从取随机数命令的应答信号中分离出8字节随机数 */
for(i=0 ; i<8; i++)
{
*OutputPtr++ = ReplyData[i];
}
/* 获取状态字 */
State = (ReplyData[8]<<8)|ReplyData[9];
}
else // 取4字节随机数
{
Read_Esam(ReplyData,6);
/* 从取随机数命令的应答信号中分离出4字节随机数 */
for(i=0 ; i<4; i++)
{
*OutputPtr++ = ReplyData[i];
}
/* 获取状态字 */
State = (ReplyData[4]<<8)|ReplyData[5];
}
return State;
}
/****************************************************************/
/* 函数名: Extern_Authen() */
/* 功能: 发送外部认证命令,进行外部认证 */
/* 参数: */
/* Input----指向存放随机数数组的指针 */
/* KeyID----外部认证密钥标识号 */
/* Key------指向存放外部认证密钥数组的指针 */
/* Mode-------加解密方式(如果是8字节密钥选DES8=0; */
/* 否则为16字节密钥选DES16=1) */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Extern_Authen(Uint16 *Input, Uint16 KeyID, Uint16 *Key, Uint16 Mode)
{
Uint16 i,State;
/* 定义一个用来暂存随机数与外部认证密钥加密后的认证码的数据结构 */
/* 该认证码构成了外部认证命令报文的数据域 */
Uint16 Temp[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
/* 初始化接收ESAM卡应答信号的数据结构,并清空命令缓冲区 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 对获取的随机数用外部认证密钥进行加密运算 */
if(Mode == DES16)
Des16(Input,Key,Temp,EN0,1);
else
Des8(Input,Key,Temp,EN0,1);
/* 第一次发送外部认证的命令头,如果正确,应该返回0x82 */
CommandLength = 5;
Command[0] = 0x00; // 填写命令报文的头域
Command[1] = 0x82;
Command[2] = 0x00;
Command[3] = KeyID;
Command[4] = 0x08;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发外部认证命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 发送外部认证命令的命令头域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定外部认证操作是否正确 */
Read_Esam(ReplyData,1);
/* 第二次发送外部认证命令的数据域,如果正确,应该返回状态9000 */
CommandLength = 8;
for(i=0; i<8; i++) // 填写命令报文的数据域
{
Command[i] = Temp[i];
}
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发外部认证命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发外部认证命令的数据域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定外部认证操作是否正确 */
Read_Esam(ReplyData,2);
/* 从外部认证命令的应答信号中分离出状态信息 */
State = (ReplyData[0]<<8)|ReplyData[1];
return State;
}
/****************************************************************/
/* 函数名: Set_Protocol() */
/* 功能: 更改ESAM和DSP的通信协议,注意一般情况下只支持协议*/
/* 从T=1改为T=0 */
/* 参数: */
/* Mode-----协议方式(0x01:T=0-->T=1;0x10:T=1-->T=0)*/
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Set_Protocol(Uint16 Mode)
{
Uint16 i,State;
/* 初始化接收ESAM卡应答信号的数据结构,并清空命令缓冲区 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 第一次发送设置通信协议的命令头,如果正确,应该返回0x14 */
CommandLength = 5;
Command[0] = 0x80; // 填写命令报文的头域
Command[1] = 0x14;
Command[2] = 0x00;
Command[3] = 0x00;
Command[4] = 0x01;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发设置通信协议命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 发送设置通信协议命令的命令头域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定设置通信协议操作是否正确 */
Read_Esam(ReplyData,1);
/* 清空命令缓冲区 */
for(i=0; i<DATALENGTH; i++)
{
Command[i] = 0;
}
/* 第二次发送设置通信协议命令的数据域,如果正确,应该返回状态9000 */
CommandLength = 1;
if(Mode == 0x01) // 从T=0-->T=1
{
Command[0] = 0xFF; // 填写命令报文的数据域
}
else // 从T=1-->T=0,一般情况下仅支持该方式
{
Command[0] = 0xFE; // 填写命令报文的数据域
}
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发设置通信协议命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发设置通信协议命令的数据域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定设置通信协议操作是否正确 */
Read_Esam(ReplyData,2);
State = (ReplyData[0]<<8)|ReplyData[1];
return State;
}
/******************************************************************************/
/* No more */
/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -