小组成员:20165223 ,20165218
实验名称:固件程序设计
目录
一、实验内容
二、实验总结
一、实验内容
任务一:固件程序设计-1-MDK
(一)实验要求
0.注意不经老师允许不准烧写自己修改的代码
1.三人一组
2.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.1-1.5安装MDK,ULink驱动
注意:要用系统管理员身分运行uVision4,破解MDK(破解程序中target一定选ARM)
3.提交破解程序中产生LIC的截图
4.提交破解成功的截图
(二)实验步骤
- 1.安装MDK4.74
- 2.安装ULink驱动
- 3.运行UV4
- 4.按实验指导步骤用注册机产生LIC
- 5.按实验指导步骤破解MDK
任务二:固件程序设计-2-LED
(一)实验要求
0.注意不经老师允许不准烧写自己修改的代码
1.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
2.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.9”完成LED实验,提交运行结果截图
注意:打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试
3.实验报告中分析代码
(二)实验步骤
(1)向KEIL-MDK 中添加 Z32 SC-000 芯片库
- 1.安装SC-000 库
- 2.建立新工程时使用SC-000
- 3.确定cpu型号时选SC-000
- 4.成功搭建Z32工程基础环境截图
- 打开Part2-Z32-安全/实验1-LED闪烁/Z32HUA.uvproj,编译LED工程,产生bin文件
(2)将程序下载到Z32实验箱上,观察结果
- 1.用USB下载线连接电脑与实验箱,按住reboot键连开Z32两次开关,连接设备
- 2.下载代码
- 3.关掉Z32电源再打开,程序自动运行,观察结果
(3)实验结果
关闭Z32电源开关,再打开,程序自动运行,Z32核心板上L2灯(上方的红灯)持续闪烁,实验成功。
(三)代码分析
(1)实验代码及注释
-
完整代码:LED.cpp
-
主要代码:
int main(void)
{
SystemInit ();
if(0 == GPIO_GetVal(0))
{
BtApiBack(0x55555555, 0xAAAAAAAA);
}
GPIO_PuPdSel(0,0); //设置 GPIO0 为上拉
GPIO_InOutSet(0,0); //设置 GPIO0 为输出
while(1)
{
delay(100);
GPIO_SetVal(0,0); //输出低电平,点亮 LED
delay(100);
GPIO_SetVal(0,1); //输出高电平,熄灭 LED
}
}
(2)细节分析
1.SystemInit ():系统初始化,设置中断向量,使能所有中断;
2.if(0 == GPIO_GetVal(0)):判断按键,返回 boot 条件,进行程序下载;
3.GPIO0:设置其状态为上拉输出;
4.while循环:进入循环程序,delay(100)设置LED 灯间隔 100ms 持续闪烁;
5.delay延时函数:当系统时钟为内部 OSC 时钟时,延时 1ms。
任务三:固件程序设计-3-UART
(一)实验要求
0.注意不经老师允许不准烧写自己修改的代码
1.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
2.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.0”完成UART发送与中断接收实验,提交运行结果截图
注意:打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试
3.实验报告中分析代码
(二)实验步骤
(1)下载程序到Z32并运行
- 1.同任务二一样先用USB下载线连接设备并下载程序
- 2.用9针串口线将Z32模块的串口与电脑USB接口连接
-
3.打开串口调试助手(sscom),设置各个参数,观察串口通信收发的数据
- 选择Z32对应串口(COM6)
- 选择波特率为115200
- 选择校验位为Even
- 勾选“发送新行”
- 点击“打开串口”
- 选择Z32对应串口(COM6)
-
4.串口调试助手中看到收发信息
(2)实验结果
关闭Z32电源开关,再打开,程序自动运行,可以在串口调试助手看到如下实验现象:显示“A Welcome to Z32HUA! 1234567890 0xAA”,证明PC机串口已经接收到Z32串口发送来的信息。在串口调试助手的字符串输入框输入字符串“abcdefg”,点击发送按钮,可以看到串口调试助手接收到我们发送输入的字符串“abcdefg”,并显示在串口助手上。实验成功。
(三)代码分析
(1)实验代码及注释
-
完整代码:UART.cpp
-
主要代码:
int main(void)
{
SystemInit ();
if(0 == GPIO_GetVal(0))
{
BtApiBack(0x55555555, 0xAAAAAAAA);
}
UART_Init(); //初始化Uart
UART_SendByte('A'); //Uart发送一个字符A
UART_SendByte('
');UART_SendByte('
'); //换行
UART_SendString("Welcome to Z32HUA!"); //Uart发送字符串
UART_SendByte('
');UART_SendByte('
'); //换行
UART_SendNum(1234567890); //Uart发送一个十进制数
UART_SendByte('
');UART_SendByte('
'); //换行
UART_SendHex(0xAA); //Uart发送一个十六进制数
UART_SendByte('
');UART_SendByte('
'); //换行
while(1)
{
if(uart_rx_end)
{
uart_rx_end=0;
uart_SendString(shuju,shuju_lens);
}
} //等待接收中断。
}
(2)细节分析
1.SystemInit ():系统初始化,中断设置,使能所有中断;
2.if(0 == GPIO_GetVal(0)):判断按键,返回boot条件,确认是否进行程序下载;
3.UART_Init():初始化Uart,使能Uart接口,配置Uart中断并使能;
4.PC机串口向Z32串口逐行发送:单个字符“A”,字符串“Welcome to Z32HUA!”,十进制数字串“1234567890”,16进制数“0xAA”;
5.while循环:进入循环程序,等待串口中断到来并判断数据是否接收完毕,若中断到来,转入执行串口中断服务程序,待接收数据完毕,Z32将数据发回串口助手。
6.delay延时函数:当系统时钟为内部 OSC 时钟时,延时 1ms。
任务四:固件程序设计-4-国密算法
(一)实验要求
0.网上搜集国密算法标准SM1,SM2,SM3,SM4
1.网上找一下相应的代码和标准测试代码,在Ubuntu中分别用gcc和gcc-arm编译
2.四个算法的用途?
3.《密码学》课程中分别有哪些对应的算法?
4.提交2,3两个问题的答案
5.提交在Ubuntu中运行国密算法测试程序的截图
(二)实验步骤
- 1.网上搜集国密算法标准SM1、SM2、SM3、SM4,回答实验要求中T2和T3提问
// T2:四个算法的用途?
答:
SM1为对称加密。其加密强度与AES相当。该算法不公开,调用该算法时,需要通过加密芯片的接口进行调用。
SM2为非对称加密,基于ECC。该算法已公开。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。
SM3为消息摘要。可以用MD5作为对比理解。该算法已公开。校验结果为256位。
SM4为无线局域网标准的分组数据算法。对称加密,密钥长度和分组长度均为128位。
// T3:《密码学》课程中分别有哪些对应的算法?
答:
SM1对应AES算法;
SM2对应ECC算法;
SM3对应MD5算法;
SM4对应3DES算法。
- 2.网上找一下相应的代码和标准测试代码,在Ubuntu中分别用gcc和gcc-arm编译
- 3.提交在Ubuntu中运行国密算法测试程序的截图
(三)代码分析
实验代码及注释分析(点击链接查看)
(1)SM1未公开,无代码
任务五:固件程序设计-5-SM1
(一)实验要求
0.注意不经老师允许不准烧写自己修改的代码
1.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
2.参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.16”完成SM1加密实验,提交运行结果截图
注意:打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试
3.实验报告中分析代码
(二)实验步骤
(1)将程序下载到Z32并运行
- 1.先用USB下载线连接设备并下载程序
-
2.用9针串口线将Z32模块的串口与电脑USB接口连接
-
3.打开串口助手,设置参数
- 选择Z32对应串口(COM6)
- 选择波特率为115200
- 选择校验位为Even
- 点击“打开串口”
-
4.关闭电源,再打开,程序自动运行。
(2)实验箱上的操作
- 1.此时,显示屏显示:“SLE4428实验!请插入IC卡...”
- 2.插入SLE4428 IC卡,显示屏显示:“已插入SLE4428 用户代码为:D27600000400”
- 3.按下矩阵键盘的A键,显示屏显示:“按-A键校验密码 校验0xFF,0xFF”
- 4.按照显示屏提示,按下矩阵键盘的A键,显示屏接着显示:“校验成功 剩余机会:8次”
- 5.再次按下矩阵键盘的A键,进入加解密实验,显示屏显示:“加密解密实验 1.加密 2.解密”
- 6.按下矩阵键盘的1键,进行加密,此时显示屏上显示:“看串口调试助手 A键确认加密”,观察串口助手看到加密结果
- 7.按下矩阵键盘的A键确认加密,显示屏显示:“加密完成 A键存入IC卡”,观察串口助手也显示“已将数据写入IC卡”
-
8.再按A键屏幕回到步骤5中加解密实验界面
-
9.额外将解密部分也运行了一下,串口助手的截图如下
(三)代码分析
(1)实验代码及注释
-
完整代码:SM1加解密
-
主要代码:
//主函数
int main(void)
{
SystemInit ();
if(0 == GPIO_GetVal(0))
{
BtApiBack(0x55555555, 0xAAAAAAAA);
}
/*初始化IC卡插入检测IO口GPIO6*/
GPIO_Config(6);
GPIO_PuPdSel(6,0); //上拉
GPIO_InOutSet(6,1); //输入
UART_Init();
lcd_init();
KEY_Init();
lcd_pos(0,0);//定位第一行
lcd_string("SLE4428 实验!");
//A段程序
A: while(1)
{
lcd_pos(1,0);//定位第二行
lcd_string("请插入IC卡. ");
delay(1000);
if(GPIO_GetVal(6)==0) break;
lcd_pos(1,0);//定位第二行
lcd_string("请插入IC卡.. ");
delay(1000);
if(GPIO_GetVal(6)==0) break;
lcd_pos(1,0);//定位第二行
lcd_string("请插入IC卡...");
delay(1000);
if(GPIO_GetVal(6)==0) break;
}
if(SLE4428_InitAndRST(2)!=0xFFFFFFFF) //收到ATR
{
lcd_pos(1,0);//定位第二行
lcd_string("已插入SLE4428");
}
else
{
lcd_pos(1,0);//定位第二行
lcd_string("卡不正确 ");
SLE4428_Deactivation(); //下电,去激活
delay(1000);
goto A;
}
lcd_pos(2,0);//定位第三行
lcd_string("用户代码为:");
SLE4428_ReadData(0x15,UserCode,6); //读取用户代码
lcd_pos(3,0);//定位第四行
for(UINT8 i=0;i<6;i++)
lcd_Hex(UserCode[i]) ;
while(KEY_ReadValue()!='A'); //等待A键按下
lcd_wcmd(0x01);//清屏
lcd_pos(0,0);//定位第一行
lcd_string("按-A键校验密码");
lcd_pos(1,0);//定位第二行
lcd_string("校验0xFF,0xFF");
while(KEY_ReadValue()!='A'); //等待A键按下
lcd_pos(2,0);//定位第三行
if(SLE4428_PassWord(0xFF,0xFF)==1)
lcd_string("校验成功");
else
{lcd_string("校验失败"); return 0;}
lcd_pos(3,0);//定位第四行
switch(SLE4428_ReadByte(0x03fd)) //查看剩余密码验证机会
{
case 0xff: lcd_string("剩余机会: 8次");break;
case 0x7f: lcd_string("剩余机会: 7次");break;
case 0x3f: lcd_string("剩余机会: 6次");break;
case 0x1f: lcd_string("剩余机会: 5次");break;
case 0x0f: lcd_string("剩余机会: 4次");break;
case 0x07: lcd_string("剩余机会: 3次");break;
case 0x03: lcd_string("剩余机会: 2次");break;
case 0x01: lcd_string("剩余机会: 1次");break;
case 0x00: lcd_string("剩余机会: 0次");break;
default: break;
}
while(KEY_ReadValue()!='A'); //等待A键按下
//B段程序
B: lcd_wcmd(0x01);//清屏
lcd_pos(0,0);//定位第一行
lcd_string("加密解密实验");
lcd_pos(1,0);//定位第二行
lcd_string("1.加密");
lcd_pos(2,0);//定位第三行
lcd_string("2.解密");
do
{
C=KEY_ReadValue();
}
while(C!='1'&&C!='2'); //等待1或2键按下
lcd_wcmd(0x01);//清屏
if(C=='1') goto jiami;
else if(C=='2') goto jiemi;
else ;
//加密程序
jiami:
lcd_pos(0,0);//定位第一行
lcd_string("观看串口调试助手");
lcd_pos(1,0);//定位第二行
lcd_string("A 键确认加密");
UART_SendString("将加密以下数据:
");
for(UINT8 i=0;i<16;i++)
{
UART_SendHex(jiamiqian[i]);
}
UART_SendString("
");
UART_SendString("加密密钥:
");
for(UINT8 i=0;i<16;i++)
{
UART_SendHex(jiamimiyue[i]);
}
UART_SendString("
");
while(KEY_ReadValue()!='A'); //等待A键按下
SM1_Init(jiamimiyue); //SM1初始化
SM1_Crypto(jiamiqian, 16, 0, 0, 0,jiamihou); //进行加密
SM1_Close(); //关闭安全模块
UART_SendString("加密后的数据:
");
for(UINT8 i=0;i<16;i++)
{
UART_SendHex(jiamihou[i]);
}
UART_SendString("
");
lcd_pos(2,0);//定位第三行
lcd_string("加密完成");
lcd_pos(3,0);//定位第四行
lcd_string("A 键存入IC卡");
while(KEY_ReadValue()!='A'); //等待A键按下
for(UINT8 i=0;i<16;i++)
{
SLE4428_Write_Byte(0x20+i,jiamihou[i]); //设置IC卡 0x20地址为存储加密数据的地址
}
UART_SendString("已将数据写入IC卡。
");
UART_SendString("
");
goto B;
//解密程序
jiemi:
lcd_pos(0,0);//定位第一行
lcd_string("观看串口调试助手");
lcd_pos(1,0);//定位第二行
lcd_string(" A键读取IC卡数据");
while(KEY_ReadValue()!='A'); //等待A键按下
SLE4428_ReadData(0x20,jiemiqian,16);
UART_SendString("读取的数据为:
");
for(UINT8 i=0;i<16;i++)
{
UART_SendHex(jiemiqian[i]);
}
UART_SendString("
");
lcd_wcmd(0x01);//清屏
lcd_pos(0,0);//定位第一行
lcd_string("读取成功");
lcd_pos(1,0);//定位第二行
lcd_string("选择密钥解密:");
lcd_pos(2,0);//定位第三行
lcd_string("1.正确密钥");
lcd_pos(3,0);//定位第四行
lcd_string("2.错误密钥");
do
{
C=KEY_ReadValue();
}
while(C!='1'&&C!='2'); //等待1或2键按下
lcd_wcmd(0x01);//清屏
if(C=='1')
{
for(UINT8 i=0;i<16;i++)
jiemimiyue[i] = jiamimiyue[i];
}
else if(C=='2')
{
for(UINT8 i=0;i<16;i++)
jiemimiyue[i] = cuowumiyue[i];
}
else ;
UART_SendString("将使用以下密钥进行解密:
");
for(UINT8 i=0;i<16;i++)
{
UART_SendHex(jiemimiyue[i]);
}
UART_SendString("
");
lcd_pos(0,0);//定位第一行
lcd_string("A 键确认解密");
while(KEY_ReadValue()!='A'); //等待A键按下
SM1_Init(jiemimiyue); //SM1初始化
SM1_Crypto(jiemiqian, 16, 1, 0, 0,jiemihou); //进行解密
SM1_Close(); //关闭安全模块
lcd_pos(1,0);//定位第二行
lcd_string("解密完成");
lcd_pos(2,0);//定位第三行
lcd_string("A 键返回");
UART_SendString("解密后的数据为:
");
for(UINT8 i=0;i<16;i++)
{
UART_SendHex(jiemihou[i]);
}
UART_SendString("
");
UART_SendString("
");
while(KEY_ReadValue()!='A'); //等待A键按下
goto B;
SLE4428_Deactivation(); //下电,去激活,实验结束
while(1)
{
}
}
(2)细节分析
- 主函数:
1.SystemInit ():系统初始化,中断设置,使能所有中断;
2.if(0 == GPIO_GetVal(0)):判断按键,返回boot条件,确认是否进行程序下载;
3.GPIO_Config(6):初始化IC卡插入检测端口GPIO6;
4.GPIO:将GPIO设为上拉输入;
5.UART_Init()、cd_init()、KEY_Init():串口初始化;LCD12864初始化;矩阵键盘初始化;
6.lcd_pos(x,0):用于定位显示屏上第x+1行(例 lcd_pos(1,0),定位第二行);
7.lcd_string("xxxxxxx"):显示屏上显示的内容。
- A段程序(A):
//if-else 结构:判断是否收到ATR(矩阵键盘按下A键),是则继续,否则执行else部分
1.第二行显示“请插入IC卡”,等待卡片插入;
2.SLE4428 IC卡正确插入,第二行显示“已插入SLE4428”,卡片插入错误则第二行显示“卡不正确 ”;
3.IC卡正确插入,则显示“用户代码为:XXXXXXXXXX”(XXXXXXXXXX代表用户的代码),等待按下键盘的“A”键;
4.按下“A”键,显示屏第一行显示“按-A键校验密码”,第二行显示“校验0xFF,0xFF”,等待“A”键按下。
5.按下“A”键,若校验密码正确,显示屏第三行显示“校验成功”,否则显示“校验失败”,第四行显示剩余密码验证机会次数“剩余机会: X次”(X初始最大为8,最小0,当校验密码错误验证一次后,X减1),等待“A”键按下。
- B段程序(B):
1.按下“A”键,显示屏第一行显示“加密解密试验”,第二、三行分别显示“1.加密”、“2.解密”两个选项。
2.等待按键按下:如果“1”按下,跳转至加密程序段,如果“2”按下,跳转至解密程序段;
- 加密程序段(jiami):
1.第一行显示“观看串口调试助手”,第二行显示“A键确认加密”,通过串口发送字符串“将加密以下数据:”并将加密前的数据发送至PC机,发送换行,串口继续发送“加密密钥:”并将加密密钥数组发送至PC机,发送完毕等待“A”键按下;
2.按下“A”键后,SM1初始化;
3.进行SM1加密;
4.关闭SM1加密安全模块;
5.通过串口发送字符串“加密后的数据:”并将加密后的数据发送至PC机,换行,在液晶屏第三行显示“加密完成”,第四行显示“A键存入IC卡”,等待“A”键按下。当“A”键按下后,向SLE4428 IC卡加密后的数据,通过串口向PC发送“已将数据写入IC卡。”跳转至B段程序。
- 解密程序段(jiemi):
1.屏幕第一行显示“观看串口调试助手”,第二行显示“A键读取IC卡数据”,当“A”键按下,读取SLE4428 IC卡解密前数据,通过串口发送“读取的数据为:”至PC机并发送解密前的数据至PC机。在显示屏的四行分别显示“读取成功”,“选择密钥解密”,“1.正确密钥”,“错误密钥”,等待按键“1”或“2”按下。如果“1”按下,解密密钥为正确的密钥,“2”按下,解密密钥为错误的密钥,然后通过串口发送“将使用以下密钥进行解密:”并将相应的解密密钥数据发送至PC机。发送完毕,第一行显示“A键确认解密”,等待“A”键按下。
2.按下“A”键后,SM1初始化;
3.进行SM1解密;
4.关闭SM1解密安全模块;
5.显示屏第二行显示“解密完成”,第三行显示“A键返回”,通过串口将“解密后的数据为:”和解密后的数据发送至PC机,发送完毕等待“A”键按下,若“A”键按下,跳转至B段程序。
6.断电,去除IC卡激活,实验结束。
二、实验总结
(一)遇到的问题
(1)任务一,在破解MDK时遇到如下问题:
- 直接打开uVision4后,点File>>License Management,报错如下
-
点击确定后却仍能进入到License Management中,于是按照实验指导步骤复制CID,再运行keil-MDK注册机,粘贴CID并选择ARM,点击generate生成LIC
-
将生成的LIC复制回License Management下方的LIC空格中,点击Add LIC,报错如下
解决方法:
- 上网搜索后发现原因是没有以管理员的身份打开uVision4,重新用管理员身份打开UV4后一路无报错,最终成功完成破解
(2)任务四,在编译运行SM2test.c测试代码时遇到如下报错:
解决方法:
- 在网上查询原因后,得知首先要下载一个OpenSSL库文件
- 经过Linux下OpenSSL静态库编译及使用上面的方法,编译出/.a文件,如图所示:
- 再次编译运行即可
(二)分析与总结
- 经过上一次实验,我和队友已经对Z32实验箱有了基本的认识,因此本次实验在环境设置方面没有遇到什么障碍。
- 在将代码从本机下载到实验箱的过程中有遇到难题,即用USB连接好后,无论如何都无法连接上设备,后来发现在按住reboot键后打开关闭开关一次的时候已经连接上了,可能是实验箱的原因(?)
- 实验时在任务四中耗时最长,除了在网上搜索代码花了很长时间以外,测试代码的运行也让人头痛了很久,最终还是成功编译运行了这几个算法。
- 实验时间虽短,但前期的准备工作是必不可少的,实验之前我和队友就已经将各个任务都捋了一遍,以便真正在实验室中能顺利完成实验,最终也还完成的较成功,这与两个人的努力是分不开的。希望下次实验也能顺利完成。