0%

侧信道攻击学习笔记1

简介

指令能耗差异

  • 本篇将跟着官方的chipwhisperer-jupyter教程sca101的**Lab 2_1A - Instruction Power Differences **学习CPU运行不同指令时消耗的能量差异

  • 首先可以看到sca101目录下有三个Lab 2_1A - Instruction Power Differences 的.ipynb文件,其实从后缀就可以看出,第二个是主程序的代码,第一个对应的是拥有Chipwhisperer硬件时可运行的代码,第三个是没有硬件时模拟运行的代码

    image-20220813175523509

  • 打开MAIN的ipynb,可以看到,最前面有提示选择模拟的代码块或者硬件的代码块复制到这个notebook代码中

    image-20220813175941844

  • 打开HARDWARE的ipynb,可以看到最前面有以下提示,意思是:需要根据你的硬件设备先设置相应平台类型,CWLite和CW1200的SCOPETYPE选择'OPENADC',CWNANO则选择'CWNANO';如果目标板为STM32(如:CWLITEARM的目标板就是这个)PLATFORM选择'CWLITE',如果目标板为XMEGA(如:CWLITEXMEGA的目标板就是这个)则选择'CWLITEXMEGA'

    image-20220813180223510

  • 这里我的硬件是CWLITEXMEGA所以选择

    1
    2
    SCOPETYPE = 'OPENADC'
    PLATFORM = 'CWLITEXMEGA'
  • 设置好后,把所有HARDWARE的ipynb的代码复制到MAIN的ipynb中执行

  • 编译目标板固件,上面的设置就是为了编译输出合适的目标板固件

    image-20220813190104862

  • 用USB连接设备,继续往下运行,正常运行会输出Found ChipWhisperer

    image-20220813190238161

  • 给目标板烧录新编译的固件

    image-20220813190406861

  • 再往下就是MAIN ipynb的代码了

    image-20220813190456892

  • 接着可以看到如下提示,意思是,这里只需要关注单个指令的能量消耗,而不关注串口通信的能量消耗,所以需要去'hardware/victims/firmware/simpleserial-base-lab2'目录下修改simpleserial-base.c的代码,找到get_pt函数,删除或者注释调末尾的simpleserial_put调用语句,保存后重新编译并上传至目标板

    image-20220813190633871

    image-20220813190913530

  • 编译,只需重新执行前面make命令的代码块,即可

    1
    2
    3
    %%bash -s "$PLATFORM"
    cd ../../../hardware/victims/firmware/simpleserial-base-lab2
    make PLATFORM=$1 CRYPTO_TARGET=NONE
  • 然后再执行前面的给目标板烧录固件的代码即可

    1
    cw.program_target(scope, prog, "../../../hardware/victims/firmware/simpleserial-base-lab2/simpleserial-base-{}.hex".format(PLATFORM))
  • 接着往下执行,可以查看目标板的能量消耗曲线

    image-20220813200838496

  • 接着往下可以看到如下提示,大意是修改simpleserial-base.c中的代码,让CPU重复执行单一命令20次,看能否从能量消耗曲线中看出该命令所对应的位置,其中需要用"volatile"关键字修饰变量,避免编译器对该代码进行优化(将这些指令直接替换为这些运算的最终结果)。对于不同的目标板,建议选则的指令不一样,如:ARM(STM32)的目标板建议测试乘法运算,XMEGA和AVR则建议测试加法运算(因为这类设备乘法运算消耗更大)

    image-20220813201148039

  • 按照上面提示在simpleserial-base.c的get_pt函数中添加测试的加法代码

    image-20220813202109830

  • 重新编译并烧录进目标板后,再次画能量消耗图,可以看到如下结果

    image-20220813202453123

  • 对比上图和一开始的图片,可以看到,上面前面部分明显出现20个尖峰,结合代码可知,这20个尖峰其实就是目标板运算20次A+=2所对应的能量消耗

  • 再往下可以看到如下提示,大意是,“你可能觉得很奇怪,为什么我们不用一个循环而是复制粘贴一行代码20次。将这个替换为循环你就知道为什么了,需要注意的是循环的变量同样要用volatile修饰

    image-20220813202903264

  • 按照上述提示,将该代码改写为for 循环并用volatile修饰循环计数 i,保存并重新编译上传至目标板

    image-20220813203442632

  • 再次画出能量消耗图,如下图,可以看到,虽然同样出现20个周期性的峰型,但是对比复制粘贴执行的能量消耗,下图耗时更久,波形更复杂些

    image-20220813203554149

  • 往下可以看到提示,大意是“你可能觉得很奇怪,为什么循环执行更复制粘贴执行的能量消耗结果不一样?如果你熟悉汇编,你可以去查看simpleserial-base-lab2文件夹下的.lss(编译输出的中间文件)。或者看下面这个C伪代码。正如你所看到的,微控制器比起执行重复粘贴的代码,循环需要做更多的事情(比较大小,循环体,循环计数+1)。如果i的变量不用volatile修饰,那么通常会将循环展开(即将循环优化为复制粘贴的代码),有volatile可以避免编译器进行这项优化。当然展开循环会导致代码块大小增大,所以有时编译器为了优化代码块大小而避免展开循环”

    image-20220813203853260

  • 再往下可以看到如下提示信息,大意是让我们测试高消耗的运算,对于ARM建议测试除法运算,对于AVR/XMEGA则建议测试乘法运算

    image-20220813213322870

  • 但是按照提示将+=2改为*=2后,重新编译并上传目标板后,抓取的能量消耗图与前面相比却并没有太大区别

    image-20220813213516138

    image-20220813213643346

  • 按下面的提示,可以知道,改为复杂运算后,应该会花更多的时间运算而且消耗更多的能量,但是上面*=2的与前面+=2却并没有太大区别

    image-20220813213827759

  • 不过想到编译器可能对2的倍数的乘法运算有优化,将乘法优化为移位运算了(如*2优化为<<1),于是把2改为3,重新编译测试,结果一出来,果然乘法消耗明显更大

    image-20220813214350672

  • 再来试试除法,根据提示的意思是XMEGA中的除法开销会巨大,如下图,下图这其实只是1次除法运算的能量消耗图而不是20次,如此可见XMEGA中的除法消耗的确非常大。同样从单次除法运算中出现多个尖峰可以推测,可以推测XMEGA的除法是循环运算一些简单指令得到的

    image-20220813214930241

总结

  • CPU/微控制器执行不同指令会有不同能量消耗和时间消耗
  • 编译器可能会在编译时对一些代码做一些优化,如:把简单的运算之间替换为运算结果,循环展开等,所以有时候测试某些运算/指令的能量消耗时,需要特别留意最终的可执行程序是否被编译器优化过的