📄 esam_function.c
字号:
/* 读返回的状态信号,以确定创建Key操作是否正确 */
Read_Esam(ReplyData,2);
/* 获取状态字 */
State = (ReplyData[0]<<8)|ReplyData[1];
return State;
}
/****************************************************************/
/* 函数名: Create_Binaryfile() */
/* 功能: 建立带线路加密和MAC保护的二进制文件 */
/* 参数: */
/* FileID-----2字节长度的文件标识符 */
/* FileLen----2字节长度的文件空间大小 */
/* RrRight----读权限 */
/* WrRight----写权限 */
/* SafeKeyID--线路保护密钥标识(0x00,0x01,0x02,0x03)*/
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Create_Binaryfile(Uint16 FileID, Uint16 FileLen, Uint16 RrRight, Uint16 WrRight, Uint16 SafeKeyID)
{
Uint16 i,State;
/* 清空命令缓冲区和接收返回信息的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 第一次发送创建线路保护二进制文件的命令头,如果正确,应该返回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卡发创建线路保护二进制文件命令 */
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 = 7;
Command[0] = 0xE8; // 填写命令报文的数据域
Command[1] = (FileLen&0xFF00)>>8;
Command[2] = FileLen&0x00FF;
Command[3] = RrRight;
Command[4] = WrRight;
Command[5] = 0xFF;
switch(SafeKeyID)
{
case 0x00:
Command[6] = 0x7F; break;
case 0x02:
Command[6] = 0x75; break;
case 0x03:
Command[6] = 0x70; break;
default:
Command[6] = 0x7A; break;
}
/* 将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;
}
/****************************************************************/
/* 函数名: Write_Binaryfile() */
/* 功能: 将数据加密并写入带线路加密和MAC保护的二进制文件 */
/* 参数: */
/* InputPtr---指向存放欲写入数据数组的指针 */
/* DataLen----欲写入数据的实际长度(不大于MAXDATA) */
/* Offset-----写入数据相对文件的2字节偏移量 */
/* Keys-------指向存放线路保护密钥数组的指针 */
/* Mode-------加解密方式(如果是8字节密钥选DES8=0; */
/* 否则为16字节密钥选DES16=1) */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Write_Binaryfile(Uint16 *InputPtr,Uint16 DataLen, Uint16 Offset, Uint16 *Keys, Uint16 Mode)
{
Uint16 i,j,BlockNum,ModNum,State;
Uint16 InitValue[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
Uint16 MAC[4] = {0x00,0x00,0x00,0x00};
Uint16 PlainText[DATALENGTH];
Uint16 DesValue[DATALENGTH];
Uint16 *TempPtr;
/* 清空命令缓冲区和接收返回信息的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
PlainText[i] = 0;
DesValue[i] = 0;
}
/* 计算输入的数据一共可以分成多少个数据块 */
BlockNum = (DataLen+1)/8+1;
ModNum = (DataLen+1)%8;
/* 构造数据块,让它为8字节的倍数 */
PlainText[0] = DataLen;
for(i=1; i<=DataLen; i++)
{
PlainText[i] = *InputPtr++;
}
if(ModNum != 0) // 如果输入不是8字节的整数倍
{
PlainText[DataLen+1] = 0x80; // 添0x80;
j = 7-ModNum;
for(i=1; i<=j; i++) // 如果在添0x80后还不足8字节,在其后补0
{
PlainText[DataLen+1+i] = 0x00;
}
}
/* 先保存一下,因为2次用到Keys */
TempPtr = Keys;
/* 调用DES加密算法,用线路保护密钥将欲输入的数据加密 */
if(Mode == DES16) // 如果线路保护密钥为16个字节,采用3DES算法
Des16(PlainText,TempPtr,DesValue,EN0,BlockNum);
else // 如果线路保护密钥为8个字节,采用单DES算法
Des8(PlainText,TempPtr,DesValue,EN0,BlockNum);
/* 首先取4字节随机数,构成初始报文 */
State = Get_Random(InitValue, 0x04);
Command[0] = 0x04;
Command[1] = 0xD6;
Command[2] = (Offset&0xFF00)>>8;
Command[3] = Offset&0x00FF;
Command[4] = BlockNum*8+4;
j = BlockNum*8; // 8*BlockNum字节密文数据
for(i=0; i<j; i++)
{
Command[5+i] = DesValue[i];
}
j = 5+BlockNum*8; // 计算MAC算法的输入数据长度
/* 调用MAC算法,计算命令报文的4字节MAC码 */
if(Mode == DES16)
MAC16_Algorithm(InitValue, Command, j, Keys, MAC);
else
MAC8_Algorithm(InitValue, Command, j, Keys, MAC);
/* 清空除命令头以外的数据 */
for(i=5; i<DATALENGTH; i++)
{
Command[i] = 0;
}
/* 第一次发送写二进制文件明令报文的头域,长度为5字节,如果结果正确,返回值是0xD6 */
CommandLength = 5;
/* 将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 */
j = BlockNum*8; // 8*BlockNum字节密文数据
CommandLength = j+4;
for(i=0; i<j; i++) // 填写的密文数据
{
Command[i] = DesValue[i];
}
for(i=0; i<4; i++) // 填写MAC码
{
Command[j+i] = MAC[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;
}
/****************************************************************/
/* 函数名: Read_Binaryfile() */
/* 功能: 从带线路加密和MAC保护的二进制文件读出密文数据 */
/* 参数: */
/* Offset-----读出数据相对文件的2字节偏移量 */
/* DataLen----欲读出的数据长度(16进制表示) */
/* Keys-------指向存放线路保护密钥数组的指针 */
/* OutputPtr--指向存放解密后数据数组的指针 */
/* Mode-------加解密方式(如果是8字节密钥选DES8=0; */
/* 否则为16字节密钥选DES16=1) */
/* 返回值: */
/* 返回unsigned short int型的16bits整数 */
/* 如果正确,返回值等于9000 */
/****************************************************************/
extern Uint16 Read_Binaryfile(Uint16 Offset, Uint16 DataLen, Uint16 *Keys, Uint16 *OutputPtr, Uint16 Mode)
{
Uint16 i,j,State;
Uint16 DataField[8];
Uint16 InitValue[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
Uint16 DesValue[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
Uint16 PlainText[DATALENGTH];
Uint16 CipherText[DATALENGTH];
Uint16 MAC[4] = {0x00,0x00,0x00,0x00};
Uint16 *TempPtr;
/* 清空命令缓冲区和接收返回信息的数据结构 */
for(i=0; i<DATALENGTH; i++)
{
ReplyData[i] = 0;
Command[i] = 0;
PlainText[i] = 0;
CipherText[i] = 0;
}
/* 先保存一下,因为3次用到Keys */
TempPtr = Keys;
/* 计算应该反馈回的密文数据块 */
//BlockNum = (DataLen+1)/8+1;
/* 填写读二进制文件的原始数据域 */
DataField[0] = DataLen;
DataField[1] = 0x80;
for(i=0; i<6; i++) // 最后6个字节域补0
{
DataField[2+i] = 0x00;
}
/* 调用DES加密算法,用线路保护密钥将欲输入的数据加密 */
if(Mode == DES8)
Des8(DataField,TempPtr,DesValue,EN0,1);
else
Des16(DataField,TempPtr,DesValue,EN0,1);
/* 首先取4字节随机数,构成初始报文 */
State = Get_Random(InitValue, 0x04);
PlainText[0] = 0x04;
PlainText[1] = 0xB0;
PlainText[2] = (Offset&0xFF00)>>8;
PlainText[3] = Offset&0x00FF;
PlainText[4] = 0x0C; // 8字节密文数据加4字节的MAC码
for(i=0; i<8; i++)
{
PlainText[5+i] = DesValue[i];
}
/* 先保存一下,因为3次用到Keys */
TempPtr = Keys;
/* 调用MAC算法,计算命令报文的4字节MAC码 */
if(Mode == DES8)
MAC8_Algorithm(InitValue, PlainText, 13, TempPtr, MAC);
else
MAC16_Algorithm(InitValue, PlainText, 13, TempPtr, MAC);
/* 第一次发送读二进制文件明命令报文的头域,长度为5字节,如果结果正确,返回值是0xB0 */
CommandLength = 5;
Command[0] = 0x04;
Command[1] = 0xB0;
Command[2] = (Offset&0xFF00)>>8;
Command[3] = Offset&0x00FF;
Command[4] = 0x0C;
/* 将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++)
{
ReplyData[i] = 0;
Command[i] = 0;
}
/* 第二次发送读二进制文件命令的数据域,如果正确,应该返回状态9000 */
CommandLength = 12;
for(i=0; i<8; i++) // 填写的密文数据
{
Command[i] = DesValue[i];
}
for(i=0; i<4; i++) // 填写MAC码
{
Command[8+i] = MAC[i];
}
/* 将ESAM卡的I/O端设为输入,准备向ESAM卡发送写二进制文件命令的数据域 */
SYSCNTL1 = 0x60;
Delay_Time(200);
/* 向ESAM卡发写二进制文件命令的数据域 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -