侧信道与故障注入攻击

学习笔记

Posted by X1ng on February 26, 2021

侧信道和故障注入的攻击很多都是对加解密过程的攻击,由于太菜了密码一个不熟,先学了一下用来当作栗子的密码

由于写笔记的时候已经没有设备可以操作了,只记录一下理论知识

加密算法

RSA加密算法

RSA是一种非对称加密算法

公钥与私钥的产生

  1. 随机选择两个不同大质数 p 和 q,计算 N=p * q

  2. 根据欧拉函数,求得 φ(N)=φ(p) * φ(q)=(p−1) * (q−1)

  3. 选择一个小于 φ(N) 的整数 e,使 e 和 φ(N) 互质。并求得 e 关于 φ(N) 的模反元素,命名为 d,有

    φ(N) mod (e * d) = 1(表示 φ(N) % (e * d) == 1)

  4. 将 p 和 q 的记录销毁

此时,(N,e) 是公钥,(N,d) 是私钥。

消息加密

首先需要将消息 以一个双方约定好的格式转化为一个小于 N,且与 N 互质的整数 m。如果消息太长,可以将消息分为几段,这也就是我们所说的块加密,后对于每一部分利用如下公式加密:

c ≡ m^e mod N (^表示平方;明文为m,经过加密后产生密文c)

消息解密

利用密钥 d 进行解密。

m ≡ c^d mod N

如果获取密钥d即可对密文进行解密

AES加密算法

AES是一种分组加密算法,通过迭代的加密操作对数据进行加密

AES128、AES192、AES256分别表示密钥长度128、192、256的加密,其迭代轮数分别为10、12、14

AES在分组的时候将每一个明文块长度分为128bit,也就是16字节,不满足16字节则需要进行填充

(如图,按照顺序填充列可以写成行列式形式)

填充策略:

  • NoPadding(要求明文必须是16字节的整数倍)

  • PKCS5Padding(默认)

    明文块少于16个字节,在明文块末尾补足相应数量的字符,且每个字节的值等于缺少的字符数

    如明文:{1,2,3,4,5,a,b,c,d,e}缺少6个字节,则补全为{1,2,3,4,5,a,b,c,d,e,6,6,6,6,6,6}

  • ISO10126Padding

    明文块少于16个字节,在明文块末尾补足相应数量的字节,最后一个字符值等于缺少的字符数,其他字符填充随机数

    如明文:{1,2,3,4,5,a,b,c,d,e}缺少6个字节,则可能补全为{1,2,3,4,5,a,b,c,d,e,5,c,3,G,$,6}

AES128加密的大致流程

  • 初始轮(Initial Round) 1次
  • 普通轮(Rounds) N次
  • 最终轮(Final Round) 1次

首先可以知道一开始密钥为128位,也就是16字节,经过扩展密钥得到最后的176字节

按照普通轮的顺序

  1. 字节代替

    把明文块的每一个字节都按照S盒替代成另外一个字节

    S盒:

      0 1 2 3 4 5 6 7 8 9 a b c d e f
    0 0x63 0x7c 0x77 0x7b 0xf2 0x6b 0x6f 0xc5 0x30 0x01 0x67 0x2b 0xfe 0xd7 0xab 0x76
    1 0xca 0x82 0xc9 0x7d 0xfa 0x59 0x47 0xf0 0xad 0xd4 0xa2 0xaf 0x9c 0xa4 0x72 0xc0
    2 0xb7 0xfd 0x93 0x26 0x36 0x3f 0xf7 0xcc 0x34 0xa5 0xe5 0xf1 0x71 0xd8 0x31 0x15
    3 0x04 0xc7 0x23 0xc3 0x18 0x96 0x05 0x9a 0x07 0x12 0x80 0xe2 0xeb 0x27 0xb2 0x75
    4 0x09 0x83 0x2c 0x1a 0x1b 0x6e 0x5a 0xa0 0x52 0x3b 0xd6 0xb3 0x29 0xe3 0x2f 0x84
    5 0x53 0xd1 0x00 0xed 0x20 0xfc 0xb1 0x5b 0x6a 0xcb 0xbe 0x39 0x4a 0x4c 0x58 0xcf
    6 0xd0 0xef 0xaa 0xfb 0x43 0x4d 0x33 0x85 0x45 0xf9 0x02 0x7f 0x50 0x3c 0x9f 0xa8
    7 0x51 0xa3 0x40 0x8f 0x92 0x9d 0x38 0xf5 0xbc 0xb6 0xda 0x21 0x10 0xff 0xf3 0xd2
    8 0xcd 0x0c 0x13 0xec 0x5f 0x97 0x44 0x17 0xc4 0xa7 0x7e 0x3d 0x64 0x5d 0x19 0x73
    9 0x60 0x81 0x4f 0xdc 0x22 0x2a 0x90 0x88 0x46 0xee 0xb8 0x14 0xde 0x5e 0x0b 0xdb
    a 0xe0 0x32 0x3a 0x0a 0x49 0x06 0x24 0x5c 0xc2 0xd3 0xac 0x62 0x91 0x95 0xe4 0x79
    b 0xe7 0xc8 0x37 0x6d 0x8d 0xd5 0x4e 0xa9 0x6c 0x56 0xf4 0xea 0x65 0x7a 0xae 0x08
    c 0xba 0x78 0x25 0x2e 0x1c 0xa6 0xb4 0xc6 0xe8 0xdd 0x74 0x1f 0x4b 0xbd 0x8b 0x8a
    d 0x70 0x3e 0xb5 0x66 0x48 0x03 0xf6 0x0e 0x61 0x35 0x57 0xb9 0x86 0xc1 0x1d 0x9e
    e 0xe1 0xf8 0x98 0x11 0x69 0xd9 0x8e 0x94 0x9b 0x1e 0x87 0xe9 0xce 0x55 0x28 0xdf
    f 0x8c 0xa1 0x89 0x0d 0xbf 0xe6 0x42 0x68 0x41 0x99 0x2d 0x0f 0xb0 0x54 0xbb 0x16

    比如字节a[0,0]='a'0x61,按照S盒替换为b[0x6,0x1]=0xef,也就是经过替换后a[0,0]=0xef

  2. 行位移

    第一行不变

    第二行循环左移1个字节

    第三行循环左移2个字节

    第四行循环左移3个字节

  3. 列混淆

    经过行位移后的矩阵每一列要和一个名为修补矩阵(fixed matrix)的二维常量数组做矩阵“相乘”,得到对应的输出列

  4. 加轮密钥

    让输入数组的每一个字节与密钥数组相同位置的字节异或

    并且进行密钥扩展(其扩展的算法是可逆的,即根据后16字节密钥可以推算出第一轮对应16字节的密钥)

也就是说,整个AES128加密流程就是在第一轮明文与密钥异或一遍之后,经过9轮普通轮的四种变换,在最后一轮第10轮再进行一次除了列混淆以外的三种变换,完成加密

如果获得任意一轮密钥,结合S逆盒等已知信息可以获得所有密钥并对密文进行解密

示波器基础

数字示波器

采集电压信号

  • 采样:设置采样率(每秒采集信号的数量),一般为芯片信号频率的5-10倍

  • 量化:设置垂直分辨率、垂直范围

  • 触发:示波器记录的开始信号

搭建采集环境

无源高阻探头要求一端接地

  • 加一个电阻,使用有源差分探头采集电阻两端的电压,通过计算出流过电路板的电流来测量电路板的功率

  • 在接地端加一个电阻,采集电阻两端的电压,通过计算出流过电路板的电流来测量电路板的功率

    但是可能会造成电阻两端接地

  • 使用电流探头,通过测量出流过电路板的电流来测量电路板的功率

  • 使用电磁探头,通过测量芯片表面的电磁辐射来测量电路板的功率

侧信道攻击

其原理是电路能量消耗与参与运算的数据、进行的操作有关

在预测密钥的作用下,通过电路模型我们能够得到所有中间运算结果。再根据能量消耗对中间结果的依赖关系,可以得到预测的能量消耗信息输出

软件功耗模型

  • 汉明重量模型

    汉明重量:一串符号中非零符号的个数

    由于CPU处理寄存器、总线中数据后预充电将所有的比特值设为1,01转换有能量变化可能泄露数据,所以电路功耗与写入寄存器的数据的汉明重量近似呈线性相关

    T(功耗) = k(常数) * HW(x)(汉明重量) + d(常数)

  • 汉明距离模型

    汉明距离:两个相同长度的二进制数中,对应位不同的数量,也就是两个二进制数异或后1的数量(汉明重量)

    某时刻在电路中有器件发生翻转,即由高电平变为低电平或者反之,就会产生动态功耗;否则只产生静态功耗

    翻转的bit越多,电路的功耗越大

    器件翻转前后功耗大小与翻转前后的二进制数的汉明距离近似呈线性相关

    T(功耗) = k(常数) * HD(V0, V1)(汉明距离) + d(常数)

简单功率分析——SPA(Simple channel analysis)

SPA攻击RSA密钥

RSA 可被 SPA 攻击的理论基础来自于 RSA 中包含的快速幂取余算法

快速幂算法如下

C 代码实现为

int PowerMod(int a, int b, int c)
{
    int ans = 1;
    a = a % c;
    while(b>0) {
        if(b % 2 == 1) // 当b为奇数时会多执行下面的指令
            ans = (ans * a) % c;
        b = b/2;
        a = (a * a) % c;
    }
    return ans;
}

快速幂的计算过程中会逐位判断指数的取值,并会采取不同的操作

所以在程序进行解密的时候,可从能量迹中还原出密钥 d(上图以及代码中的b) 的取值,直接得到的值是 d 的二进制取值的逆序

SPA攻击AES算法结构

由于不同操作,能量迹波形特征不同,可以通过分析能量迹来确定AES加密时使用的算法结构

差分功率攻击——DPA(Differential Power Analysis)

将大量明文pi与密钥进行加密运算,获得多条能量迹Ti,再将这些明文与猜测的密钥k(256次),进行运算得到多个中间值x,再将x某个状态字节的值作为区分函数将数据分为两组,求出两组的功耗均值, 再将 2 个功耗均值求差,并对其进行统计分析以得出密钥(逐比特)

看例子理解

以AES128为例

可以将其视为除了最后一轮外每轮变换步骤为

  1. 加轮密钥
  2. 字节代替
  3. 行位移
  4. 列混淆

的加密方法

攻击步骤:

  1. 对pi进行加密操作,通过示波器获取i条能量迹Ti

  2. 逐字节对密钥k进行爆破,每个字节需要爆破256次(0~0xff),对于每个猜测的k的值都进行一遍以下操作来逐字节爆破密钥

  3. 进行i次 将明文pi与猜测的k进行异或后根据S盒替换得到中间值xi 的操作(也就是说对于密钥k的每个字节,都有i*256个x)

  4. 从异或后的中间结果xi中某个状态字节的值作为区分函数(比如判断最后一个字节是否为1)将i个数据对应的i条能量迹(此处的能量迹是使用正确密钥对pi进行加密时采集的能量迹Ti)分为两组,求出两组的功耗均值, 再将 2 个功耗均值求差

  5. 只有正确的密钥可以将 2 组具有差异的功耗数据区分开,因此正确密钥的差分功耗值是最大的

    (图形大概如图)

这么做的目的是:

对比汉明重量的功耗模型,计算出得xi时,xi中的每个比特,为1的能耗与为0的能耗不同

假设对于某一个猜测的k,计算得出xi时,xi中某个比特为1时功耗为P+a,为0时功耗为P

则只有在这i组能量迹按 使用猜测密钥k加密产生的xi这一比特是否为1分出来的组 与 使用正确密钥加密产生的值的这一比特是否为1分出来的组 一致的情况下,求出两组的功耗均值, 再将 2 个功耗均值求差,其差分功耗a才会比较突出的显示在差分曲线图中的某个点

否则相互抵消的情况下不能将该点的差分功耗明显地区分出来

能量相关分析——CPA(Correlation Power Analysis)

通过 用多个明文与猜测的密钥值所计算出的中间值的汉明重量 与 正常解密流程的能量迹各点 进行线性相关对比,如果存在线性相关性极大的点则说明该计算中间值的过程(使用这个密钥的过程)存在于加密流程中,即可判断密钥正确(逐字节)

看例子理解

以AES128为例

可以将其视为除了最后一轮外每轮变换步骤为

  1. 加轮密钥
  2. 字节代替
  3. 行位移
  4. 列混淆

的加密方法

运算的主要功耗在于字节代替阶段,对于1、2变换,可以概括为将输入数据与密钥逐字节异或后根据S盒进行替换

攻击步骤:

  1. 对pi进行加密操作,通过示波器获取i条能量迹Ti

  2. 对逐字节的密钥k进行爆破,每个字节需要爆破256次(0~0xff),对于每个猜测的k的值都进行一遍以下操作来逐字节爆破密钥

  3. 进行i次 将明文pi与猜测的k进行异或后根据S盒替换得到xi 的操作

  4. 计算出xi的汉明重量hwi,与对应能量迹Ti中每个点进行相关性分析,生成相关性曲线图

    如果某个由猜测的k产生的x的汉明重量与能量迹T中一个点相关系数很大(在-1~1之间),也就是说在每次明文pi与该猜测的密钥k运算结果xi的汉明重量都与明文pi与正确密钥加密时能量迹曲线某点一致,则表示计算产生x(使用这个密钥的过程)在整个加密过程中出现过(相关系数极大的时间点),即可判断该k是正确的密钥

侧信道防御技术

  • 时间维度:随机伪操作/乱序操作——随机化密码设备的能量消耗
  • 振幅纬度:增加噪声/降低功耗——降低能量消耗信噪比,使不同操作数/操作具有一样的能量消耗
  • 掩码技术:改变中间值

故障注入

通过外界干扰改变设备正常逻辑,让程序进行能被利用的出错,并进行利用

if(pay_pwd_is_correct)
	transfer_money();
else
	reject_operation();
  • 非侵入式攻击:改变电压等外部变量
  • 半侵入式攻击:拆解设备,不与芯片直接接触
  • 侵入式攻击:改变或破坏设备内部电路

原理及种类

关键路径:组合逻辑电路从输入到输出所经历的正常时延

  • 电压故障注入:电压降低,关键路径变长,大于时钟间隔
  • 时钟毛刺注入:时钟上升沿提前到来,时钟间隔小于关键路径
  • 电磁脉冲注入:电磁效应形成局部感应电流(具体模型学术界仍在讨论)
  • 激光注入:光电效应引起载流子能级跃迁,PN节异常导通
  • 温度:一般情况下环境温度升高,关键路径变长

目的

  • 绕过一些安全机制(文件访问权限、安全启动)
  • 产生错误密文或者签名
  • 组合攻击

故障注入参数

  • 攻击时刻
  • 攻击强度
  • 作用时间
  • 空间位置

调试参数过程

  1. 记录不同参数对应设备状态
  2. 反复尝试,缩小参数范围
  3. 根据经验,调整强度和作用时长
  4. 借助侧信道分析,监控故障注入时间点

错误模型

  1. 字节错误
  2. 字错误
  3. 比特错误
  4. 随机错误
  5. 固定为0/1

攻击步骤

  1. 确定攻击目标

    • 修改寄存器的值

    • 修改内存(DRAM/SRAM的值)

    • 修改地址

    • 修改总线信号

    • 执行错误指令

    • 密码算法

      … …

  2. 仔细阅读目标设备数据手册和资料

    • 芯片正常和最大工作电压

    • 芯片时钟频率

      … …

  3. 寻找目标设备产生的有用信号

    • 利于找到攻击的时间点
    • 利于缩短攻击事件范围
    • 利于找到攻击的物理位置
    • 信噪比高,容易实现
    • 电路板信号可引出改造

    • GPIO管教信号

    • 电路板指示灯LED

    • UART、SPI、IIC

    • 调试接口

    • 芯片复位

      … …

  4. 确定攻击方式

  5. 样品准备(十个以上)

  6. 攻击结果判断条件

  7. 开始攻击

栗子

PANDA-CTF 2019 story

向串口发送”story”,串口会输出一串字符串的前一小段,其最后部分是flag,触发为pin8,在串口输出的时候pin8为高电平

关键流程是将待发送的数据长度加载到寄存器R1中,R2置为0,之后将R2自增进行输出

可以在 将待发送的数据长度加载到寄存器R1中 时对其进行攻击,让R1中保存的待输出的字符个数变多,从而输出最后的flag

攻击流程

  1. 由于在第一个字符输出前,输出串口会先拉低作为起始位,所以可以通过侧信道分析找到从触发拉高开始到第一个字符发送到串口前(输出串口拉低)的这段时间作为我们的攻击时间,从而攻击将载入R1的这个操作

    (图中红色为触发pin8,蓝色为输出串口)

  2. 通过电磁故障注入设备在该段时间对芯片进行攻击

  3. 通过继电器上电和下电控制设备进行重启,多次尝试,调整攻击参数(触发时间、攻击时间、强度、脉宽、位置等)

参考资料

什么是AES算法?(整合版)

CTF-wiki

纽创信安——bilibili

《功耗分析攻击中的功耗与数据相关性模型》

《差分能量攻击所需样本数量研究》