2019-2020-1 20175208 20175218 20175230 实验二 固件程序设计

2019-2020-1 20175208 20175218 20175230 实验二 固件程序设计

一、实验内容

1、固件程序设计-1-MDK

  1. 注意不经老师允许不准烧写自己修改的代码
  2. 三人一组
  3. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.1-1.5安装MDK,JLink驱动,注意,要用系统管理员身分运行uVision4,破解MDK(破解程序中target一定选ARM)
  4. 提交破解程序中产生LIC的截图
  5. 提交破解成功的截图

2、固件程序设计-2-LED

  1. 注意不经老师允许不准烧写自己修改的代码
  2. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
  3. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.9”完成LED实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
  4. 实验报告中分析代码

3、固件程序设计-3-UART

  1. 注意不经老师允许不准烧写自己修改的代码
  2. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
  3. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.0”完成UART发送与中断接收实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
  4. 实验报告中分析代码

4、固件程序设计-4-国密算法

  1. 网上搜集国密算法标准SM1,SM2,SM3,SM4
  2. 网上找一下相应的代码和标准测试代码,在Ubuntu中分别用gcc和gcc-arm编译
  3. 四个算法的用途?
  4. 《密码学》课程中分别有哪些对应的算法?
  5. 提交2,3两个问题的答案
  6. 提交在Ubuntu中运行国密算法测试程序的截图

5、固件程序设计-5-SM1

  1. 注意不经老师允许不准烧写自己修改的代码
  2. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.4” KEIL-MDK 中添加 Z32 SC-000 芯片库,提交安装截图
  3. 参考云班课资源中“信息安全系统实验箱指导书.pdf “第一章,1.16”完成SM1加密实验,注意“打开Z32的电源开关前,按住Reboot按键不放,两次打开电源开关,Z32即可被电脑识别,进行下载调试。提交运行结果截图
  4. 实验报告中分析代码

6、固件程序设计-6-清理

  1. 实验结束后,把实验室原来的网线插回,否则以后做实验的同学无法开机
  2. 只有用实验室机器的小组做
  3. 提交你们小组使用的计算机的编号照片
  4. 提交插好网线的照片
  5. 提交盖好后盖的照片

二、实验小组成员及分工

  1. 成员列表
学号 姓名
20175208 张家华
20175218 陈敬勇
20175230 滕星
  1. 实验分工

实验内容:三人共同完成实验

撰写博客:陈敬勇

三、实验步骤

1、固件程序设计-1-MDK

  1. 参考信息安全系统实验箱指导书的第一章,1.1-1.5安装好MDK,JLink驱动

  1. 运行keil-MDK注册机破解MDK
  2. 破解程序中产生LIC的截图

  1. 破解成功的截图

2、固件程序设计-2-LED

  1. 安装sc000库,打开Z32文件夹下的软件资料,找到Support.exe文件,双击进行安装

  2. 安装完成后,运行keil uVision4,进行工程基础编程环境搭建。其中,芯片库选择 Generic SC000 Device Database。ARM 结构目录,选择 SC000。

  1. 打开“ Z32 开发指南 实验1-LED闪烁”目录的工程文件。双击打开Z32HUA.uvproj文件。点击编译,进行编译。

  1. 将实验箱接入电源,把笔记本电脑与实验箱连接好,在软件资料文件夹下的Z32下载调试工具中打开Z32下载调试工具 NZDownloadTool.exe 。打开实验箱的电源开关前,按住 Reboot 键不放,两次打开电源开关, Z32 即可被电脑识别,进行下载调试。

  2. 出现设备已连接,设备选择中显示芯片型号后,点击浏览,选择LED闪烁文件夹下bin文件夹中的Z32HUA.bin,最后点击下载。

  1. 关闭实验箱 Z32 的电源开关,再打开,程序自动运行,此时可以看到实验箱 Z32 核心板上 L2 灯开始闪烁。

  1. 代码分析

main 函数代码如下:

int main(void)
{
    /*********************此段代码勿动*********************/
    //系统中断向量设置,使能所有中断
    SystemInit();
        //返回 boot 条件
    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
    }
}
//延时函数,当系统时钟为内部延时函数,当系统时钟为内部OSC时钟时,延时1ms
void delay(int ms)
{
    int i;
    while(ms----)
    {
        for(i=0;i<950;i++) ;for(i=0;i<950;i++) ;
    }
}

主函数代码的执行过程为:

  • 系统初始化,中断设置,使能所有中断;
  • 判断按键,返回 boot 条件,确认是否进行程序下载;
  • 设置 GPIO0 状态为上拉输出;
  • 进入循环程序, LED 灯间隔 100ms 闪烁;

3、固件程序设计-3-UART

  1. Z32 SC-000 芯片库,安装截图

  1. 打开“ Z32 开发指南 实验 2 UART 发送与中断接收 ”,双击打开Z32HUA.uvproj文件。点击编译,进行编译。

  1. 保持上面实验电脑与实验箱的连接状态,在软件资料文件夹下的Z32下载调试工具中打开Z32下载调试工具 NZDownloadTool.exe 。打开实验箱的电源开关前,按住 Reboot 键不放,两次打开电源开关, Z32 即可被电脑识别,进行下载调试。
  2. 出现设备已连接,设备选择中显示芯片型号后,点击浏览,选择 UART 发送与中断接收文件夹下bin文件夹中的 Z32HUA.bin,最后点击下载。

  1. 用 9 针串口线将 Z32 模块的串口与电脑 USB 接口连接。

  2. 在电脑上打开串口助手,选择对应的串口号,设置波特率为 115200 ,偶校验( Even ),选中“发送新行”,然后打开串口。其中串口号可通过设备管理器查看。

  1. 关闭实验箱 Z32 电源开关,再打开,程序自动运行,可以在串口调试助手看到显示“ 0 0xAA ”。

  1. 在串口调试助手的字符串输入框输入字符串“90”,然后点击发送按钮。这时,可以看到串口调试助手接收到我们发送输入的字符串“90”并显示在串口助手上。发送“aaa90”,可见“aaa90”。

  1. 代码分析

Uart.c

extern UINT8 shuju[64];
extern UINT8 shuju_lens;
extern UINT8 uart_rx_num;
extern UINT8 uart_rx_end;

void UART_IrqService(void)
{
//*****your code*****/
    UARTCR &= ~TRS_EN;
    {
        do
        {
            shuju[uart_rx_num] = UARTDR;
            if(shuju[uart_rx_num]=='\r'||shuju[uart_rx_num]=='\n')
            {
                shuju_lens = uart_rx_num;
                uart_rx_num=0;
                uart_rx_end=1;
            }
            else
                uart_rx_num++;
        }
        while(FIFO_NE & UARTISR);
    }
    UARTCR |= TRS_EN;
}

/**
* @函数:波特率设置
* @set:0-默认波特率115200,其他:需根据时钟源和分频计算出set = 时钟(hz)/波特率
* @返回: none
*/
void UART_BrpSet(UINT16 set)
{
    UINT16 brp=0;
    UINT8 fd=0;
    if(0 == set)
    {
    //uartband@115200bps
        fd = SCU->UARTCLKCR & 0x80;
        switch(fd)
        {
        case 0x80:/*外部时钟12M晶振*/
            brp = 0x0068;
            break;
        case 0x00:/*内部时钟*/
            brp = 0x00AD;
            break;
        default:
            brp = 0x00AD;
            break;
        }
        fd = SCU->UARTCLKCR & 0x7f ;
        brp =brp/(fd+1);
    }
    else
    {
        brp = set;
    }
    UARTBRPH = (UINT8)((brp >> 8) & 0xFF);
    UARTBRPL = (UINT8)((brp) & 0xFF);
}

/**
* @函数:初始化
* @返回:none
*/
void UART_Init(void)
{
    IOM->CRA |= (1<<0);//使能Uart接口
    SCU->MCGR2 |= (1<<3); //使能Uart总线时钟
    
    /******配置Uart时钟(建议使用外部晶振)******/
    SCU->SCFGOR |= (1<<6);// 使能外部晶振
    SCU->UARTCLKCR |= (1<<7);//使用外部时钟
    //SCU->UARTCLKCR &= ~(1<<7);//使用内部OSC时钟
    
    UART_BrpSet(0);//设置波特率为默认115200
    UARTISR = 0xFF;//状态寄存器全部清除
    UARTCR |= FLUSH; //清除接收fifo
    UARTCR = 0;//偶校验
    
    /******配置中断使能******/
    UARTIER |= FIFO_NE;
    //UARTIER |= FIFO_HF;
    //UARTIER |= FIFO_FU;
    //UARTIER |= FIFO_OV;
    //UARTIER |= TXEND;
    //UARTIER |= TRE;
    ModuleIrqRegister(Uart_Exception, UART_IrqService);//挂载中断号
}

/**
* @函数:Uart发送一个字节
* @dat:  要发送的数据字节
* @返回:None
*/
void UART_SendByte(UINT8 dat)
{
    UARTCR |= TRS_EN;
    UARTDR = dat;
    do
    {
        if(UARTISR & TXEND)
        {
            UARTISR |= TXEND;//清除发送完成标志,写1清除
            break;
        }
    }
    while (1);
    UARTCR &= (~TRS_EN);
}

/**
* @函数:Uart发送一个字符串
* @str:  要发送的字符串
* @返回:None
*/
void UART_SendString(UINT8 * str)
{
    UINT8 *p ;
    p=str;
    while(*p!=0)
    {
        UART_SendByte(*p++);
    }
}

/**
* @函数:Uart发送某一长度的字符串
* @buf:  要发送的字符串
* @length:  要发送的长度
* @返回:None
*/

void uart_SendString(UINT8 buf[],UINT8 length)
{
    UINT8 i=0;
    while(length>i)
    {
        UART_SendByte(buf[i]);
        i=i+1;
    }
}

/**
* @函数:Uart发送一个十进制整数
* @num:  要发送的整数
* @返回:None
*/
void UART_SendNum(INT32 num)
{
    INT32 cnt = num,k;
    UINT8 i,j;
    if(num<0)
    {
        UART_SendByte('-');
        num=-num;
    }
    //计算出i为所发数据的位数
    for(i=1;; i++)
    {
        cnt = cnt/10;
        if(cnt == 0)
            break;
    }
    //算出最大被除数从高位分离
    k = 1;
    for(j=0; j<i-1; j++)
    {
        k = k*10;
    }
    //分离并发送各个位
    cnt = num;
    for(j=0; j<i; j++)
    {
        cnt = num/k;
        num = num%k;
        UART_SendByte(0x30+cnt);
        k /= 10;
    }
}

/**
* @函数:Uart发送一个16进制整数
* @dat:  要发送的16进制数
* @返回:None
*/
void UART_SendHex(UINT8 dat)
{
    UINT8 ge,shi;
    UART_SendByte('0');
    UART_SendByte('x');
    ge = dat%16;
    shi = dat/16;
    if(ge>9)
        ge+=7;//转换成大写字母
    if(shi>9)
        shi+=7;
    UART_SendByte(0x30+shi);
    UART_SendByte(0x30+ge);
    UART_SendByte(' ');
}

/**
* @函数:Uart接收一个字节
* @param receive addsress
* @返回:flag
*/
UINT8 UART_GetByte(UINT8 *data)
{
    UINT8 ret= 0;
    if(0 != (UARTISR & FIFO_NE))
    {
        *data = UARTDR;
        ret = 1;
    }
    return ret;
}
/**
* @函数:Uart 接收多个字节
* @param receive addsress
* @len:长度
* @返回:none
*/
void UART_Receive(UINT8 *receive, UINT8 len)
{
    while(len != 0)
    {
        if(len >= 4)
        {
            while (!(UARTISR & FIFO_FU));
            *receive++ = UARTDR;
            *receive++ = UARTDR;
            *receive++ = UARTDR;
            *receive++ = UARTDR;
            len -= 4;
        }
        else if(len >= 2)
        {
            while (!(UARTISR & FIFO_HF));
            *receive++ = UARTDR;
            *receive++ = UARTDR;
            len -= 2;
        }
        else
        {
            while (!(UARTISR & FIFO_NE));
            *receive++ = UARTDR;
            len--;
        }
    }
}

主函数

UINT8 shuju_lens;
UINT8 shuju[64];
UINT8 uart_rx_num;
UINT8uart_rx_end;
int main(void)
{
    /*********************此段代码勿动***********************/
//系统中断向量设置,使能所有中断
    SystemInit ();
// 返回boot条件
    if(0 == GPIO_GetVal(0))
    {
        BtApiBack(0x55555555, 0xAAAAAAAA);
    }
    /*********************此段代码勿动***********************/
    UART_Init();    //初始化Uart
    UART_SendByte('A');//Uart发送一个字符A
    UART_SendByte('\r');
    UART_SendByte('\n');//换行
    UART_SendString("Welcome to Z32HUA!");  //Uart发送字符串
    UART_SendByte('\r');
    UART_SendByte('\n');//换行
    UART_SendNum(1234567890);//Uart发送一个十进制数
    UART_SendByte('\r');
    UART_SendByte('\n');//换行
    UART_SendHex(0xAA);//Uart发送一个十六进制数
    UART_SendByte('\r');
    UART_SendByte('\n');//换行
    while(1)
    {
        if(uart_rx_end)
        {
            uart_rx_end=0;
            uart_SendString(shuju,shuju_lens);
        }
    }  //等待接收中断。
}
//延时函数,当系统时钟为内部OSC时钟时,延时1ms
void delay(int ms)
{
    int i;
    while(ms--)
    {
        for(i=0; i<950; i++) ;
    }
}

代码的执行过程为:

  • 系统初始化,中断设置,使能所有中断;
  • 判断按键,返回 boot 条件,确认是否进行程序下载;
  • 初始化 Uart ,使能 Uart 接口,配置 Uart 中断并使能;
  • 先发送单个字符“ A ”,换行,再发送字符串 Welcome to Z32H UA!换行,发送数字串“ 1234567890 ”,换行,再发送 16 位数“ 0xAA ”,换行。
  • 进入 while 循环程序,等待串口中断到来并判断数据是否接收完毕,若中断到来,转入执行串口中断服务程序,待接收数据完毕, Z32 将数据发回串口助手。

4、固件程序设计-4-国密算法

  1. 通过上网搜集国密算法标准SM1,SM2,SM3,SM4
  2. 把相应的代码和标准测试代码下载到Ubuntu,在Ubuntu中分别用gcc和gcc-arm编译

码云链接

  1. 四个算法的用途:
  • SM1 为对称加密。其加密强度与AES相当。
  • SM2为非对称加密,基于ECC。由于该算法基于ECC,故其签名速度与秘钥生成速度都快于RSA。
  • SM3 消息摘要。校验结果为256位。SM3算法的压缩函数与SHA-256的压缩函数具有相似的结构,但是SM3算法的设计更加复杂。
  • SM4 无线局域网标准的分组数据算法。目的是为了加密保护静态储存和传输信道中的数据对称加密,密钥长度和分组长度均为128位。
  1. 《密码学》课程中分别对应的算法
  • SM1对应AES算法
  • SM2对应ECC算法
  • SM3对应MD5算法
  • SM4对应3DES算法
  1. 在Ubuntu中运行国密算法测试程序的截图

5、固件程序设计-5-SM1

  1. Z32 SC-000 芯片库,安装截图

  1. 打开“ Z32 开发指南 实验 8-SM1”,双击打开 Z32HUA.uvproj 文件。点击编译,进行编译。

  1. 保持上面实验电脑与实验箱的连接状态,在软件资料文件夹下的Z32下载调试工具中打开Z32下载调试工具 NZDownloadTool.exe 。打开实验箱的电源开关前,按住 Reboot 键不放,两次打开电源开关, Z32 即可被电脑识别,进行下载调试。
  2. 出现设备已连接,设备选择中显示芯片型号后,点击浏览,选择 SM1 文件夹下bin文件夹中的 Z32HUA.bin,最后点击下载。

  1. 保持上面实验的连接状态,跟上面一样,在电脑上打开串口助手,选择对应的串口号,设置波特率为 115200 ,偶校验( Even ),选中“发送新行”,然后打开串口。

  1. 关闭 Z32 电源开关,再打开,程序自动运行,此时可以看到显示屏显示“SLE4428实验!请插入实验!请插入IC卡...”。

  1. 插入那张白卡,即 SLE4428 IC 卡,显示屏第三行显示:“用户代码为:”,第四行显示用户代码“ D27600000400 ”。

  1. 按下矩阵键盘的“ A ”键,屏幕第一行显示提示“按 A 键校验密码”并在第二行显示两个字节的校验密码“校验 0xFF 0xFF ”。

  1. 按下矩阵键盘的“ A ”键,屏幕第三行显示“校验成功”,第四行显示校验剩余机会“剩余机会: 8 次”。

  1. 按下矩阵键盘的“ A ”键,则屏幕第一行显示“加密解密实验”,第二、三行分别显示选项“ 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 ”。

  1. 按“ 1 ”键选择正确的密钥后,屏幕提示 A 键确认解密”,此时串口显示“将使用以下密钥进行解密: 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F ”。

  1. 按“ A ”键确认解密后,屏幕提示“解密完成 A 键返回”,此时串口显示“解密后的数据为 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F ”。

  1. 按“ A ”键返回加/解密选择菜单。

  1. 按“ 2 ”进行解密实验,用错误的秘钥解密。屏幕提示“观看串口调试助手 A 键读取 IC 卡数据”。

  1. 按“ A ”键后,此时屏幕显示“读取成功 选择密钥解密: 1. 正确密钥 2. 错误密钥”。串口显示“读取的数据:为: 0x7E 0xDC 0xA3 0x7B 0xBA 0x53 0x84 0xAC 0x0B 0x75 0x50 0x45 0x2E 0xEC 0x4F 0x4F ”。

  1. 按“ 2 ”键选择错误的密钥后,屏幕提示 A 键确认解密”,此时串口显示“将使用以下密钥进行解密: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 ”。

  1. 按“ A 键确认解密后,屏幕提示“解密完成 A 键返回”,此时串口显示“解密后的数据为 0xB9 0x8C 0xB6 0x40 0xA2 0xD2 0x83 0xD0 0x64 0x6E 0x54 0x26 0x86 0x6D 0x5A 0xF5 ”。而正确的原始数据为 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F ”,所以解密失败。

  1. 代码分析

主函数代码如下:

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];
    }
    elseif(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++) ;
    }
}

主函数代码的执行过程为:

  • 系统初始化,中断设置,使能所有中断;
  • 判断按键,返回 boot 条件,确认是否进行程序下载;
  • 初始化 IC 卡插入检测端口 GPIO6
  • 串口初始化;
  • LCD12864 初始化;
  • 矩阵键盘初始化;
  • 液晶屏第一行显示字符串“ SLE4428 实验!”。

A段程序:

  • 第二行显示“请插入 IC 卡”,等待卡片插入;
  • SLE4428 IC 卡正确插入,第二行显示“已插入 SLE4428 ”,卡片插入错误则第二行显示“卡不正确
  • IC 卡正确插入,则显示“用户代码为: XXXXXXXXXX XXXXXXXXXX 代表用户的代码),等待按下键盘的“ A ”键
  • 按下“ A ”键,显示屏第一行显示“按 A 键校验密码”,第二行显示“校验 0xFF,0xFF ”,等待 A ”键按下。
  • 按下“ A ”键,若校验密码正确,显示屏第三行显示“校验成功”,否则显示“校验失败”,第四行显示剩余密码验证机会次数“剩余机会: X次”( X 初始最大为 8 ,最小 0 ,当校验密码错误验 证一次后, X 减 1等待“ A ”键按下

B段程序:

  • 按下“ A ”键,显示屏第一行显示“加密解密试验”,第二、三行分别显示“ 1. 加密”、“ 2. 解密”两个选项。等待按键按下:如果“ 1 ”按下跳转至加密程序段,如果“ 2 ”按下,跳转至解密程序段

加密程序段:

  • 第一行显示“观看串口调试助手”,第二行显示“ A 键确认加密”,通过串口发送字符串“将加密以下数据:”并将加密前的数据发送至 PC 机,发送换行,串口继续发送“加密密钥:”并将加密密钥数组发送至 PC 机,发送完毕等待“ A ”键按下
  • 按下“ A ”键后 SM1 初始化;
  • 进行 S M1 加密;
  • 关闭 SM1 加密安全模块;
  • 通过串口发送字符串“加密后的数据:”并将加密后的数据发送至 PC 机,换行,在液晶屏第三行显示“加密完成”,第四行显示“ A 键存入 IC 卡”,等待“ A ”键按下。当 A ”键按下后,向 SLE4428 IC 卡加密后的数据,通过串口向 PC 发送“已将数据写入 IC 卡。”跳转至 B 段程序。

解密程序段:

  • 屏幕第一行显示“观看串口调试助手”,第二行显示“ A 键读取 IC 卡数据”,当“ A ”键按下,读取 SLE4428 IC 卡解密前数据,通过串口发送“读取的数据为:”至 PC 机并发送解密前的数据至 PC 机。在 显示屏的四行分别显示“读取成功”,“选择密钥解密”,“ 1. 正确密钥”,“错误密钥”,等待按键“ 1 ”或 2 ”按下。如果 1 ”按下,解密密钥为正确的密钥,“ 2 ”按下,解密密钥为错误的密钥,然后通过串口发送“将使用以下密钥进行解密:”并将相应的解密密钥数据发送至 PC 机。发送完毕,第一行显示“ A 键确认解密”,等待“ A ”键按下。
  • 按下“ A ”键后 SM1 初始化;
  • 进行 SM1 解密;
  • 关闭 SM1 解密安全模块;
  • 显示屏第二行显示“解密完成”,第三行显示“ A 键返回”,通过串口将“解密后的数据为:”和解密后的数据发送至 PC 机,发 送完毕等待“ A键按下,若“ A ”键按下,跳转至 B 段程序。
  • 断电,去除 IC 卡激活,实验结束。

四、实验中遇到的问题及解决方法

问题:第三个实验是要显示“ A Welcome to Z32HUA! 1234567890 0xAA ”,但是在实验时,我们显示的是“0 0xAA”

解决方法:查看代码,发现没有问题,然后试过发送和接受功能,发现发送和接受功能都是正常的。重新编译程序,重新做一遍,发现还是显示不了,但是功能却能正常实现,就暂时放下了。

五、实验感想

这次实验总的来说比较简单,根据指导书一步一步往下做就可以了。通过这次实验,也了解到了国密算法标准SM1,SM2,SM3,SM4的相关知识,学会了安装和破解 MDK,并且知道了配置其环境。

六、参考资料

1.实验指导

2.Arm实验箱实验环境

posted @ 2019-11-16 17:23  20175218陈敬勇  阅读(432)  评论(0编辑  收藏  举报