📄 esam_function.c
字号:
/****************************************************************/
/* 文件名: Esam_Function.c */
/* 功能: 定义ESAM卡的操作函数 */
/* 设计者: 陈湘和 */
/* 设计日期: 10/20/2004 */
/*--------------------------------------------------------------*/
/* 说明: */
/* 该文件设计了通过DSP的UART操作ESAM卡进行数据保护 */
/* 的所有相关指令,这些指令是基于T=0协议设计的,如果 */
/* 用户的ESAM芯片基于T=1协议,请在使用这些函数前用 */
/* 读写器或者在通过认证后用Set_Protocol指令将ESAM */
/* 芯片的协议改为T=0. */
/****************************************************************/
#include <stdio.h>
#include <csl.h>
#include "Uart_Function.h"
#include "DEC5502_DES.h"
#include "DEC5502_MAC.h"
/* 定义两个宏来访问系统控制寄存器 */
#define SYSCNTL1 (*(volatile int *)(0x280000))
#define SYSCNTL2 (*(volatile int *)(0x280001))
#define DES8 0
#define DES16 1
#define RSTTIME 0xAD6B // RST信号低电平时间长度取500个时钟周期
#define MAXDATA 0xA7 // 一次最多能够读写167个数据
#define DATALENGTH MAXDATA+7 // 接收命令缓冲区最大长度 =
// MAXDATA+1字节数据位+4字节MAC码+2字节状态位
Uint16 CommandLength; // 定义命令报文的实际长度变量
Uint16 Command[DATALENGTH]; // 定义存放命令报文的缓冲区,为了初始化方便
// 长度设为与接收缓冲区长度一致
Uint16 ReplyData[DATALENGTH]; // 定义接收信号缓冲区
extern Uint16 Get_Random(Uint16 *OutputPtr, Uint16 Length);
/****************************************************************/
/* 函数名: Reset_Esam() */
/* 功能: 对ESAM卡复位,并取得返回的复位应答信息 */
/* 参数: */
/* DataPtr----指向存放序列号的数组的指针 */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Reset_Esam(Uint16 *DataPtr)
{
Uint16 i,FeedValue;
/* 初始化接收ESAM卡应答信号的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
}
/* RST信号变为低电平 */
SYSCNTL2 = 0x00;
Delay_Time(200);
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收复位应答信号 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 让复位信号等待一段时间,满足复位时序要求 */
Delay_Time(RSTTIME);
/* 让ESAM脱离复位状态,从而实现ESAM复位 */
SYSCNTL2 = 0x08;
/* 读复位应答信号 */
Read_Esam(ReplyData,13);
/* 从复位应答信号中分离出序列号 */
for(i=0; i<8; i++)
{
*DataPtr++ = ReplyData[i+5];
}
/* 获取状态字 */
FeedValue = 0x9000;
return FeedValue;
}
/****************************************************************/
/* 函数名: Get_Response() */
/* 功能: 取回ESAM反馈的数据和MAC码 */
/* 参数: */
/* DataPtr-----指向存放返回数据指针数组的指针 */
/* DataLen-----欲取回的数据和MAC码总长度(以16进制 */
/* 表示,单字节长度) */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Get_Response(Uint16* DataPtr, Uint16 DataLen)
{
Uint16 i,State;
/* 清空命令缓冲区和接收数据缓冲区 */
for(i=0; i<DATALENGTH; i++)
{
Command[i] = 0;
}
/* 填写接收返回数据的命令报文 */
CommandLength = 5;
Command[0] = 0x00;
Command[1] = 0xC0;
Command[2] = 0x00;
Command[3] = 0x00;
Command[4] = DataLen;
/* 将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);
/* 获取返回信息 */
Read_Esam(ReplyData,DataLen+2);
/* 从返回信息中分离出数据和MAC码 */
for(i=0; i<DataLen; i++)
{
*DataPtr++ = ReplyData[i];
}
/* 获取状态字 */
State = (ReplyData[DataLen]<<8)|ReplyData[DataLen+1];
return State;
}
/****************************************************************/
/* 函数名: Del_Direct() */
/* 功能: 删除以前建立的目录文件(不包括MF文件) */
/* 参数: */
/* 无 */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Del_Direct(void)
{
Uint16 i,State;
/* 清空命令缓冲区 */
for(i=0; i<DATALENGTH; i++)
{
Command[i] = 0;
}
/* 填写删除目录的命令报文 */
CommandLength = 5;
Command[0] = 0x80;
Command[1] = 0x0E;
Command[2] = 0x00;
Command[3] = 0x00;
Command[4] = 0x00;
/* 将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;
}
/****************************************************************/
/* 函数名: Create_Keyfile() */
/* 功能: 建立密钥文件 */
/* 参数: */
/* FileID-----2字节长度的文件标识符 */
/* FileLen----2字节长度的文件空间大小 */
/* IncRight---增加密钥权限 */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Create_Keyfile(Uint16 FileID, Uint16 FileLen, Uint16 IncRight)
{
Uint16 i,State;
/* 清空命令缓冲区和接收返回信息的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 第一次发送创建Key文件的命令头,如果正确,应该返回0xE0 */
CommandLength = 5;
Command[0] = 0x80; // 填写命令报文的头域
Command[1] = 0xE0;
Command[2] = (FileID&0xFF00)>>8;
Command[3] = FileID&0x00FF;
Command[4] = 0x07;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发创建Key文件命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 发送创建Key文件命令的命令头域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定创建Key文件操作是否正确 */
Read_Esam(ReplyData,1);
/* 第二次发送创建Key文件命令的数据域,如果正确,应该返回状态9000 */
CommandLength = 7;
Command[0] = 0x3F; // 填写命令报文的数据域
Command[1] = (FileLen&0xFF00)>>8;
Command[2] = FileLen&0x00FF;
Command[3] = 0xFF;
Command[4] = IncRight;
Command[5] = 0xFF;
Command[6] = 0xFF;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发送创建Key文件命令的数据域 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发创建Key文件命令的数据域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定创建Key文件操作是否正确 */
Read_Esam(ReplyData,2);
/* 获取状态字 */
State = (ReplyData[0]<<8)|ReplyData[1];
return State;
}
/****************************************************************/
/* 函数名: Increase_Key() */
/* 功能: 建立(39-外部认证/主控或36-线路保护)密钥 */
/* 参数: */
/* KeyID----- 密钥标识符 */
/* KeyType----密钥类型(0x39或0x36) */
/* UseRight---密钥使用权 */
/* AltRight---密钥更改权限 */
/* NextState--后续状态(如果密钥类型0x36保留为0xFF) */
/* ErrCount---错误计数器 */
/* Keys-------指向存放欲建立密钥的数组的指针 */
/* Mode-------加解密密钥方式(如果是8字节密钥选 */
/* DES8=0;否则为16字节密钥选DES16=1) */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Increase_Key(Uint16 KeyID, Uint16 KeyType, Uint16 UseRight, Uint16 AltRight, Uint16 NextState, Uint16 ErrCount, Uint16 *Keys,Uint16 Mode)
{
Uint16 i,State,KeyLen;
/* 清空命令缓冲区和接收返回信息的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
if(Mode == DES8)
KeyLen = 8;
else
KeyLen = 16;
/* 第一次发送创建Key的命令头,如果正确,应该返回0xD4 */
CommandLength = 5;
Command[0] = 0x80; // 填写命令报文的头域
Command[1] = 0xD4;
Command[2] = 0x01;
Command[3] = KeyID;
Command[4] = KeyLen+5;
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发创建Key命令 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 发送创建Key命令的命令头域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
/* 读返回的状态信号,以确定创建Key操作是否正确 */
Read_Esam(ReplyData,1);
/* 第二次发送创建Key命令的数据域,如果正确,应该返回状态9000 */
CommandLength = KeyLen+5;
Command[0] = KeyType; // 填写命令报文的数据域
Command[1] = UseRight;
Command[2] = AltRight;
if(KeyType == 0x39) // 如果是外部认证密钥,有后续状态
Command[3] = NextState;
else // 如果是线路保护密钥,该域保留为0xFF
Command[3] = 0xFF;
Command[4] = ErrCount;
for(i=0; i<KeyLen; i++)
{
Command[5+i] = *Keys++;
}
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发送创建Key命令的数据域 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发创建Key命令的数据域 */
Write_Esam();
/* 将ESAM卡的I/O端设为输出,准备从ESAM卡接收返回状态 */
SYSCNTL1 = 0x20;
Delay_Time(200);
/* 读空接收缓冲区 */
i = UART_RGET(URRBR);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -