本小组课程设计题目:基于Z32的虚拟机制做与测试c++
本小组成员:redis
这次实验中我负责的是算法
学习GPIO原理,阅读《ARM cortex-m0权威手册》,参考Z32HUA_DEMO工程函数库(详见软件资料),经过设置经过GPIO1,GPIO2,GPIO3串行通讯控制液晶屏,实现字符显示功能。数组
12864是一种图形点阵液晶显示器。它主要采用动态驱动原理由行驱动—控制器和列驱动器两部分组成了128(列)×64(行)的全点阵液晶显示。此显示器采用了COB的软封装方式,经过导电橡胶和压框链接LCD,使其寿命长,链接可靠。安全
打开12864液晶屏串行显示实验工程文件,如图所示: 并发
12864
的代码 LCD.c
分析:LCD12864的代码包括其初始化、设定显示位置,以及写数据的函数:框架
- void lcd_sendbyte(UINT8 byte)函数的做用是串行方式发送一个字节;
- void lcd_wcmd(UINT8 cmd) 函数的做用是写指令操做到LCD12864,包括写命令,状态等指令;
- void lcd_wdat(UINT8 dat)函数是写数据操做,以并行方式从D0~D7向12864写入显示数据,先送高4位,再送低4位;
- void lcd_string(UINT8 *str)是写字符串操做;
- void lcd_init(void)是12864的初始化操做,首先对串行引脚进行初始化,设置Z32的GPIO-1,2,3为输出,分别做为片选、读写口和时钟端口并初始输出低电平,而后进行LCD的初始化,包括选择指令集,显示设置以及屏幕和光标的基本设定;
- void lcd_pos(UINT8 X,UINT8 Y)是设定12864开始显示的位置。
== LCD.c
源代码以下:==函数
/*串行发送一个字节 */ /* */ /*******************************************************************/ void lcd_sendbyte(UINT8 byte) { UINT8 i; for(i=0;i<8;i++) { GPIO_SetVal(CLK,0); GPIO_SetVal(SID,byte&0x80); GPIO_SetVal(CLK,1); byte=(byte<<1); } GPIO_SetVal(CLK,0); } /*******************************************************************/ /* */ /*写指令数据到LCD */ /* */ /*******************************************************************/ void lcd_wcmd(UINT8 cmd) { GPIO_SetVal(CS,1); delay(5); //串行不支持读操做,不可检测忙操做,这里用延时替代 lcd_sendbyte(0xf8); //送入5个连续的“1“,启动一个周期,11111,RW(0),RS(0),0 lcd_sendbyte(0xf0&cmd); //取高四位,数据分两次传送, //每一个字节的内容被送入两个字节,高四位放在第一个字节的高四位 lcd_sendbyte(0xf0&(cmd<<4)); //低四位放在第二个字节的高四位 GPIO_SetVal(CS,0); } /*******************************************************************/ /* */ /*写显示数据到LCD */ /*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */ /* */ /*******************************************************************/ void lcd_wdat(UINT8 dat) { GPIO_SetVal(CS,1); delay(5); lcd_sendbyte(0xfa); lcd_sendbyte(0xf0&dat); lcd_sendbyte(0xf0&(dat<<4)); GPIO_SetVal(CS,0); } /*******************************************************************/ /* */ /*写字符串到LCD */ /* */ /*******************************************************************/ void lcd_string(UINT8 *str) { UINT8 *p ; p=str; while(*p!=0) { lcd_wdat(*p++); } } /*******************************************************************/ /* */ /* LCD初始化设定 */ /* */ /*******************************************************************/ void lcd_init(void) { /********串行引脚初始化*******/ GPIO_InOutSet(CS,0); //设置GPIO 1,2,3为输出 GPIO_InOutSet(SID,0); GPIO_InOutSet(CLK,0); /********lcd初始化*******/ delay(50); //等待时间要大于40ms lcd_wcmd(0x30); //选择基本指令集 delay(3); lcd_wcmd(0x0c); //开显示,无游标,不反白 delay(3); lcd_wcmd(0x01); //清除显示屏幕,把DDRAM位址计数器调整为00H delay(3); lcd_wcmd(0x06); //设定光标右移,总体显示不移动 delay(3); } /*********************************************************/ /* */ /* 设定显示位置 */ /* */ /*********************************************************/ void lcd_pos(UINT8 X,UINT8 Y) { UINT8 pos; if (X==0) {X=0x80;} else if (X==1) {X=0x90;} else if (X==2) {X=0x88;} else if (X==3) {X=0x98;} pos = X+Y ; lcd_wcmd(pos); //显示地址 }
==主函数main.c源代码以下:==工具
int main(void) { /*********************此段代码勿动***********************/ //系统中断向量设置,使能全部中断 SystemInit (); // 返回boot条件 if(0 == GPIO_GetVal(0)) { BtApiBack(0x55555555, 0xAAAAAAAA); } /*********************此段代码勿动***********************/ lcd_init(); while(1) { lcd_pos(0,0);//定位第一行 lcd_string("欢迎使用Z32HUA!"); delay(1800); lcd_pos(1,0);//定位第二行 lcd_string("LCD12864液晶测试"); delay(1800); lcd_pos(2,0);//定位第三行 lcd_string("1.2.3.4.5.6.7.8."); delay(1800); lcd_pos(3,0);//定位第四行 lcd_string("A.B.C.D.E.F.G..H."); delay(1800); lcd_wcmd(0x01);//清屏 } } //延时函数,当系统时钟为内部OSC时钟时,延时1ms void delay(int ms) { int i; while(ms--) { for(i=0;i<950;i++) ; } }
一、打开“Z32开发指南\实验3-12864液晶屏串行显示”目录的工程文件。编译工程,产生后缀名为.bin的可执行代码。下图为编译成功的截图: 性能
二、将实验箱接入电源,用USB公对公线将实验箱的USB接口链接到电脑的USB接口上,在电脑上找到“Z32开发指南\2.软件资料\Z32下载调试工具”目录打开Z32下载调试工具NZDownloadTool.exe。以下图所示:
三、打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32便可被电脑识别,进行下载调试。下图中设备已链接:
四、当左边框出现“1设备已链接”,设备选择中显示芯片型号,此时就能够下载程序了。点击“下载”,左边状态提示框更新显示“程序下载成功!”实验3的程序就下载进Z32的实验板上了。
五、实验3的内容是LCD12864液晶屏的显示操做。 关闭Z32电源开关,再打开,程序自动运行,此时能够看到实验现象:屏幕上依次显示如下字符: “欢迎使用Z32HUA! LCD12864液晶测试 1.2.3.4.5.6.7.8. A.B.C.D.E.F.G.H.” 其中行与行之间显示的间隔时间约为1.8s,四行字符所有显示完成后清屏幕,从新循环显示。以下图所示:
阅读SLE4428 IC数据手册,学习SLE4428逻辑加密卡操做原理,阅读《ARM cortex-m0权威手册》(详见目录Z32开发指南\3.参考资料),参考Z32HUA_DEMO工程函数库(详见Z32开发指南\2.软件资料),经过Z32安全模块对SLE4428 IC卡进行数据读写实验。
逻辑加密存储器卡:在非加密存储器卡的基础上增长了加密逻辑电路,加密逻辑电路经过校验密码方式来保护卡内的数据对于外部访问是否开放,但只是低层次的安全保护,没法防范恶意性的攻击。
本实验所用IC卡:
SLE4428是SIMENS公司设计的逻辑加密IC卡,容量为1K*8Bit,设有两个字节的密码。只有经过了密码验证,才能够对IC卡内的没有设置写/擦除保护的内容进行写/擦除。内部有错误计数器(EC),错误计数器老是能够被写的,若是连续8次教研密码不成功,IC卡将自动被锁死,数据只能独处,不可再对数据进行写/擦除操做,也不能够再校验密码。每一个字节均可以单独的设置写/擦除保护,一单设置了写/擦除保护功能,这个字节的数据就不能在写/擦除了,并且写保护功能只能设置一次。除了密码区,其余全部字节在任什么时候候均可以读出来。
本此实验例程的详细程序请打开“Z32开发指南\实验7-SLE4428逻辑加密卡”目录文件夹下的工程文件,下面咱们对程序的主要部分作一下简单的分析。 打开SLE4428逻辑加密卡实验工程文件,如图所示:
/** * @函数: SLE4428初始化和复位 * @voltage:电压值 - 0: 1.8V (默认) * - 1: 3V * - 2: 3.3V * - 3: 5V * @返回: none */ UINT32 SLE4428_InitAndRST(UINT8 voltage) { UINT32 ATR=0; IOM->CRB &= ~(1<<4); //SCC0接口做为GPIO口 GPIO_InOutSet(8,0); //CLK输出使能 GPIO_InOutSet(9,0); //RST输出使能 GPIO_InOutSet(10,0); //IO输出使能 GPIO_PuPdSel(8,0); //CLK上拉使能 GPIO_PuPdSel(9,0); //RST上拉使能 GPIO_PuPdSel(10,0); //IO上拉使能 GPIO_SetVal(8,0) ; //CLK输出0 GPIO_SetVal(9,0) ; //RST输出0 GPIO_SetVal(10,0) ; //IO输出0 SCU->SCFGVRCARD |= (voltage<<2); //VCARD0配置为voltage SCU->SCFGVCCACTRL |= (1<<1) ; //使能vCard0电源 /******开始复位******/ GPIO_SetVal(9,1) ; //RST输出1 GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 GPIO_SetVal(9,0) ; //RST输出0 GPIO_InOutSet(10,1); //IO输入使能 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us for(UINT8 i=0;i<32;i++) { GPIO_SetVal(8,1) ; //CLK输出1 ATR = ATR|(GPIO_GetVal(10)<<i); //获取应答 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } return ATR; } /** * @函数:发送命令控制字 * @S: 控制字 * @addr:10位地址 * @Data: 数据 * @返回:none */ void SLE4428_SendCmd(UINT8 S,UINT16 addr,UINT8 Data) { UINT32 CTL=0; //命令控制字(三个字节24位) CTL |= S; //首6位控制字(S5~S0) CTL |= (addr&0x0300)>>2; //地址的A9,A8 CTL |= (addr&0x00FF)<<8; //地址的A7~A0 CTL |= Data<<16; //数据的D7~D0 GPIO_SetVal(8,0) ; //CLK输出0 GPIO_SetVal(9,1) ; //RST输出1 GPIO_InOutSet(10,0); //IO输出使能 for(UINT8 i = 0 ; i < 0x20 ; i++) ; //等待大约40us for(UINT8 i=0;i<24;i++) //输出三个字节的控制字 { GPIO_SetVal(10,CTL&0x01) ; //IO输出数据 GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us CTL = CTL>>1; } GPIO_SetVal(9,0) ; //RST输出0 GPIO_InOutSet(10,1); //IO输入使能 } /** * @函数:读取一个字节 * @addr:10位地址 * @返回:读取的数据 */ UINT8 SLE4428_ReadByte(UINT16 addr) //输入10位地址 { UINT8 Data=0; /*****命令001110(读8位,无保护位)*****/ SLE4428_SendCmd(0x0E,addr,0); /*****过滤接收前的脉冲*****/ GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ; //等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ; //等待大约40us /*****正式接收一个字节*****/ for(UINT8 i=0;i<8;i++) { GPIO_SetVal(8,1) ; //CLK输出1 Data = Data|(GPIO_GetVal(10)<<i); //读取数据 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } return Data; } /** * @函数:读取数据 * @addr:10位地址 * @str:1数组首地址 * @n: 读取长度 * @返回:None */ void SLE4428_ReadData(UINT16 addr,UINT8* str,UINT8 n) { /*****命令001110(读8位,无保护位)*****/ SLE4428_SendCmd(0x0E,addr,0); /*****过滤接收前的脉冲*****/ GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us /*****正式接收一个字节*****/ for(UINT8 j=0;j<n;j++) { *(str+j) = 0; for(UINT8 i=0;i<8;i++) { GPIO_SetVal(8,1) ; //CLK输出1 *(str+j) = *(str+j)|(GPIO_GetVal(10)<<i); //读取数据 for(UINT8 i = 0 ; i < 0x20 ; i++) ; //等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ; //等待大约40us } } } /** * @函数:验证密码(地址为0x03FE,0x03FF) * @PSC1: 第一个字节 * @PSC2: 第二个字节 * @返回:0->验证失败,1->验证成功 */ BOOL SLE4428_PassWord(UINT8 PSC1,UINT8 PSC2) { /*****第一步,写错误寄存器*****/ //命令:110010,地址:0x03FD,数据:读取该地址的数据右移1位 SLE4428_SendCmd(0x32,0x03FD,(SLE4428_ReadByte(0x03FD)>>1)); //给103个脉冲完成写操做 for(UINT8 i=0;i<103;i++) { GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } /********第二步:验证PSC1*******/ //命令:001101,地址:0x03FE,数据:PSC1 SLE4428_SendCmd(0x0D,0x03FE,PSC1); //给2个脉冲完成操做 for(UINT8 i=0;i<2;i++) { GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } /********第三步:验证PSC2*******/ //命令:001101,地址:0x03FF,数据:PSC2 SLE4428_SendCmd(0x0D,0x03FF,PSC2); //给2个脉冲完成操做 for(UINT8 i=0;i<2;i++) { GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } /********第四步:擦除错误计数器*******/ SLE4428_SendCmd(0x33,0x03FD,0xFF); //命令:110011,地址:0x03FD,数据:0xFF //给103个脉冲完成写操做 for(UINT8 i=0;i<103;i++) { GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } if(SLE4428_ReadByte(0x03FD)==0xFF) return 1; return 0; } /** * @函数:写一个字节 * @addr:10位地址 * @Byte: 要写的数据 * @返回:none */ void SLE4428_Write_Byte(UINT16 addr,UINT8 Byte) { SLE4428_SendCmd(0x33,addr,Byte); //给103个脉冲完成写操做 for(UINT8 i=0;i<103;i++) { GPIO_SetVal(8,1) ; //CLK输出1 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us GPIO_SetVal(8,0) ; //CLK输出0 for(UINT8 i = 0 ; i < 0x20 ; i++) ;//等待大约40us } } /** * @函数:接口释放,电源下电 * @返回:none */ void SLE4428_Deactivation(void) { GPIO_InOutSet(10,0); //IO输出使能 GPIO_SetVal(8,0) ; //CLK输出0 GPIO_SetVal(9,0) ; //RST输出0 GPIO_SetVal(10,0) ; //IO输出0 SCU->SCFGVCCACTRL &= ~(1<<1) ;//失能vCard0电源 SCU->CARD0VCTRL &= ~(1<<0); }
==下面介绍主函数,代码以下:==
int main(void) { /*********************此段代码勿动***********************/ //系统中断向量设置,使能全部中断 SystemInit (); // 返回boot条件 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: 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("校验失败"); 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键按下 lcd_wcmd(0x01);//清屏 B: lcd_pos(0,0);//定位第一行 lcd_string("金额:"); Money=SLE4428_ReadByte(0x10); lcd_wdat(0x30+Money/100); lcd_wdat(0x30+Money%100/10); lcd_wdat(0x30+Money%10); lcd_pos(1,0);//定位第一行 lcd_string("输入金额,A键修改"); lcd_pos(2,0);//定位第三行 for(UINT8 j=0;j<3;j++) { do { delay(5); C = KEY_ReadValue(); } while(KeyFlag != 2); //直到按下数字键,KeyFlag为2是表明数字。 lcd_wdat(C); money[j] = C-0x30; } while(KEY_ReadValue()!='A'); //等待A键按下 Money = money[0]*100+money[1]*10+money[2]; if(Money>=255) Money = 255; SLE4428_Write_Byte(0x10,Money); lcd_wcmd(0x01);//清屏 goto B; SLE4428_Deactivation(); //下电,去激活,实验结束 while(1) { } } //延时函数,当系统时钟为内部OSC时钟时,延时1ms void delay(int ms) { int i; while(ms--) { for(i=0;i<950;i++) ; } }
一、打开“Z32开发指南\实验7-SLE4428逻辑加密卡”目录的工程文件。编译工程,产生后缀名为.bin的可执行代码。 二、将实验箱接入电源,用USB公对公线将实验箱的USB接口链接到电脑的USB接口上,在电脑上找到“Z32开发指南\2.软件资料\Z32下载调试工具”目录打开Z32下载调试工具NZDownloadTool.exe。 三、打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32便可被电脑识别,进行下载调试。 四、当左边框出现“1设备已链接”,设备选择中显示芯片型号,此时就能够下载程序了。
五、点击“下载”,左边状态提示框更新显示“程序下载成功!”实验7的程序就下载进Z32的实验板上了。
实验7的内容是SLE4428逻辑加密卡实验,按照程序提示,插入SLE4428逻辑加密卡,A段程序显示用户代码并进行密码校验,B段程序读取卡片存储的金额信息并修改金额。
关闭Z32电源开关,再打开,程序自动运行,此时能够看到实验现象:显示屏第一行显示“SLE4428实验!”,第二行显示“请插入IC卡...”。
插入SLE4428 IC卡,显示屏第三行显示:“用户代码为:”,第四行显示用户代码“D27600000400”。
若插入了正确的卡片,显示出用户代码,再按下矩阵键盘的“A”键,屏幕第一行显示提示“按-A键校验密码”并在第二行显示两个字节的校验密码“校验0xFF,0xFF”。
按下矩阵键盘的“A”键,屏幕第三行显示“校验成功”,第四行显示校验剩余机会“剩余机会:8次”。
再按下矩阵键盘的“A”键,则屏幕第一行显示卡内金额数“金额:100”,第二行提示“输入金额,A键修改”。
在矩阵键盘上输入三位修改的金额数560,按下矩阵键盘的“A”键确认。发现修改变为了255,这是由于程序中写不容许大于255,若是大于只显示255.
可是能够修改成小于255的值,好比输入200试试,确认后,金额更新,屏幕上显示更改后的卡内金额“金额200”,第四行继续提示“输入金额,A键修改”,能够再次进行更改。
修改完金额后,就能够拔出IC卡,实验结束。
学习SM1加密原理,阅读《ARM cortex-m0权威手册》和《Z32HUA国密算法库用户手册》(详见目录Z32开发指南\3.参考资料),参考Z32HUA_DEMO工程函数库(详见Z32开发指南\2.软件资料),调用SM1加解密函数,实现对SLE4428 IC的数据加解密操做。
国密SM1(SM1 cryptographic algorithm),国密SM1算法是由国家密码管理局编制的一种商用密码分组标准对称算法。该算法是国家密码管理部门审批的SM1分组密码算法,分组长度和密钥长度都为128 比特,算法安全保密强度及相关软硬件实现性能与AES至关,该算法不公开,仅以IP核的形式存在于芯片中。采用该算法已经研制了系列芯片、智能IC卡、智能密码钥匙、加密卡、加密机等安全产品,普遍应用于电子政务、电子商务及国民经济的各个应用领域(包括国家政务通、警务通等重要领域)。
本此实验例程的详细程序请打开“Z32开发指南\实验8-SM1”目录文件夹下的工程文件,下面咱们对程序的主要部分作一下简单的分析。
打开SM1加解密实验工程文件,如图所示:
在user组下分别双击Main.c和SLE4428.c,就能够看到主函数代码和SLE4428程序的源代码。其中工程文件目录的algorithm文件夹包含了Z32HUA_ALG.ALG函数库,其中包含了国密的加解密算法相关函数库,SM1加解密函数的调用须要这个库的支持。 ==打开Main.c,介绍一下主函数,代码以下:==
UINT8 jiamiqian[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; UINT8 jiamimiyue[16]={0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}; UINT8 jiamihou[16]; UINT8 jiemiqian[16],jiemimiyue[16],jiemihou[16]; UINT8 cuowumiyue[16]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; UINT8 UserCode[5]; UINT8 C; int main(void) { /*********************此段代码勿动***********************/ //系统中断向量设置,使能全部中断 SystemInit (); // 返回boot条件 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: 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: 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("将加密如下数据:\r\n"); for(UINT8 i=0;i<16;i++) { UART_SendHex(jiamiqian[i]); } UART_SendString("\r\n"); UART_SendString("加密密钥:\r\n"); for(UINT8 i=0;i<16;i++) { UART_SendHex(jiamimiyue[i]); } UART_SendString("\r\n"); while(KEY_ReadValue()!='A'); //等待A键按下 SM1_Init(jiamimiyue); //SM1初始化 SM1_Crypto(jiamiqian, 16, 0, 0, 0,jiamihou); //进行加密 SM1_Close(); //关闭安全模块 UART_SendString("加密后的数据:\r\n"); for(UINT8 i=0;i<16;i++) { UART_SendHex(jiamihou[i]); } UART_SendString("\r\n"); 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卡。\r\n"); UART_SendString("\r\n"); 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("读取的数据为:\r\n"); for(UINT8 i=0;i<16;i++) { UART_SendHex(jiemiqian[i]); } UART_SendString("\r\n"); 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("将使用如下密钥进行解密:\r\n"); for(UINT8 i=0;i<16;i++) { UART_SendHex(jiemimiyue[i]); } UART_SendString("\r\n"); 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("解密后的数据为:\r\n"); for(UINT8 i=0;i<16;i++) { UART_SendHex(jiemihou[i]); } UART_SendString("\r\n"); UART_SendString("\r\n"); while(KEY_ReadValue()!='A'); //等待A键按下 goto B; SLE4428_Deactivation(); //下电,去激活,实验结束 while(1) { } } //延时函数,当系统时钟为内部OSC时钟时,延时1ms void delay(int ms) { int i; while(ms--) { for(i=0;i<950;i++) ; } }
加密程序段:
解密程序段:
一、打开“Z32开发指南\实验8-SM1”目录的工程文件。编译工程,产生后缀名为.bin的可执行代码。 二、下载程序。 三、实验8的内容是SM1加解密实验,待加密的原始数据以及加密秘钥已经内置到程序中,修改UINT8 jiamiqian[16]数组便可更换待加密数据,修改jiamimiyue[16]数组和cuowumiyue[16]便可修改正确和错误的加密密钥。 四、本实验一样使用SLE4428 IC卡做为加解密介质,按照程序提示,插入SLE4428逻辑加密卡,A段程序显示用户代码并进行密码校验,B段程序进行加密/解密选择,加密程序段进行SM1加密并将加密先后数据经过串口发送至PC机,解密程序段进行SM1解密并将解密先后数据经过串口发送至PC机。 五、咱们用9针串口线将Z32模块的串口与电脑USB接口链接。 六、若是发现链接9针串口线后虚拟机仍然没有反应,能够在虚拟机中进行链接设置,确保虚拟机与Z32芯片正常链接。以下图即为链接成功。
七、首先在电脑上打开串口助手,选择对应的串口号,设置波特率为115200,偶校验(Even),而后打开串口。 八、若是不清楚串口号选择,可在设备查看器中查看。以下图:
九、关闭Z32电源开关,再打开,程序自动运行,此时能够看到实验现象:显示屏显示“SLE4428实验!请插入IC卡...”。 十、插入SLE4428 IC卡,显示屏第三行显示:“用户代码为:”,第四行显示用户代码“D27600000400”。 十一、若是插入错误的卡片,则显示屏第二行显示:“卡不正确”。 十二、若插入了正确的卡片,显示出用户代码,再按下矩阵键盘的“A”键,屏幕第一行显示提示“按-A键校验密码”并在第二行显示两个字节的校验密码“校验0xFF,0xFF”。 1三、按下矩阵键盘的“A”键,屏幕第三行显示“校验成功”,第四行显示校验剩余机会“剩余机会:8次”。 1四、再按下矩阵键盘的“A”键,则屏幕第一行显示“加密解密实验”,第2、三行分别显示选项“1.加密”,“2.解密”。
1五、首先进行加密实验。按“1”键选择加密,屏幕第一行显示“观看串口调试助手”,第二行显示“A键确认加密”。此时,串口调试助手显示原始数据和加密密钥。
1六、按下“A”键确认加密后,屏幕第三行显示“加密完成”,第四行显示提示“A键存入IC卡”。串口调试助手显示加密后的数据。
1七、按“A”键,将加密数据存入IC卡,此时串口显示“已将数据写入IC卡”。屏幕回到加密解密实验选择菜单。 1八、下面进行解密实验。按“2”键选择解密实验后屏幕显示“观看串口调试助手 A键读取IC卡数据”。
1九、按“A”键后,此时屏幕显示“读取成功 选择密钥解密:1.正确密钥 2.错误密钥”。串口显示“读取的数据:为:0x7E 0xDC 0xA3 0x7B 0xBA 0x53 0x84 0xAC 0x0B 0x75 0x50 0x45 0x2E 0xEC 0x4F 0x4F”。
20、按“1”键选择正确的密钥后,屏幕提示“A键确认解密”,此时串口显示“将使用如下密钥进行解密:0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F”。
2一、按“A” 键确认解密后,屏幕提示“解密完成 A键返回”,此时串口显示“解密后的数据为:0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F”。
2二、按“A”键返回加/解密选择菜单。
一、破解软件MDK4.74过程当中遇到了错误提示: **错误缘由:**因为没有用管理员权限运行该软件,致使了没法成功破解。 **解决方案:**右键,以管理员身份运行该软件,再试一次便可成功。
成功截图:
二、实验二程序代码编译时遇到错误,发现了11个error,没法运行。 **错误缘由:**没有更新c++ redistributable packet 运行库,致使找不到头文件stdint.h。 **解决方案:**安装DirectX修复工具,并检测且修复。
成功截图:
三、将Z32模块连进虚拟机中,没法连进虚拟机时,能够根据提示选择虚拟机
->可移动设备
。选择Z32HUA-BOOT
来,链接到Z32。
四、串口选择不能选择错误,若是选择COM1
的话,打开串口
以后,仍然没法成功。串口没法显示内容。
COM5
,串口选择相应的COM5
,再打开时,能够成功。