具体实施方式
在一个优选的实施方式中,本发明接收到一段软件的源代码,并将该源代码分割成各种逻辑基本块。基于这些基本块的内容及其在程序的逻辑和控制流中的位置,对这些基本块进行修改以增加或者创建各基本块之间的依赖性。对基本块的修改具有扩展一些基本块的输出同时类似地扩展其它相应基本块的输入的效果。经扩展的输出包含原始输出以及通过代码修改而引入或者注入的额外信息。经扩展的输入要求原始基本块的常规输入以及经扩展的输出的额外信息。
参考在整个说明书中使用的概念和术语的以下解释将会更好地理解本发明优选实施方式的以下描述。
将联锁(interlock)定义为系统、机构或装置的各部分之间的连接,其中系统的某个或多个部分Y的操作以下述方式受到某另外一个或多个部分X操作的影响:篡改一个或多个部分X的性态将很可能引起一个或多个部分Y的功能失效或故障。
即,系统中已联锁的各部分之间的连接是在篡改的情况下主动易损的。本发明的目的是提供用于引入(inducing)影响特定SBE性态的这种主动易损性的一般性强有力的目标工具。
当攻击者篡改程序的数据或代码时,动机通常是以某种特定方式修改程序的性态。例如,如果应用程序检查在用户可以使用该应用程序之前必须被验证的某段数据(例如密码或数据权标),则攻击者可能希望产生该程序的类似于原始版本的新版本,但该新版本不执行这种验证从而获得对该应用程序的功能的不受限制且不经检查的访问。类似地,如果应用程序为了计费的目的而对使用进行计量,则攻击者可能希望修改该应用程序,使得它能够执行相同服务,但其使用量(usage metric)记录为较小或者没有使用,由此减少或者消除使用该应用程序的费用。如果应用程序是试用版,其构造成正常但只能在有限时间段内执行,以期望有人会购买正式版,则攻击者可能希望修改试用版,以便无限扩展该有限时间段,由此避免正式版的费用。
因此,对程序的软件或者数据进行篡改的特征在于它是寻求特定性态改变的目标导向的活动。如果攻击者简单地希望毁坏应用程序,则这会有许多不需要复杂攻击的平凡方式来实现:例如,可以删除应用程序可执行文件,或者可以通过改变该文件的随机位来随机地修改该文件,使其很可能无法有效地执行。本发明的保护不是要防止具有这种有限目标的攻击,而是要防止针对特定性态修改的更复杂的攻击。
因此,由本发明的方法和系统引入的在篡改时的主动易损性通过确保不能实现特定性态改变而阻止了攻击者的企图,相反,代码改变使系统性态混乱而毫无目的,因此攻击者不是获得了期望结果而是仅仅实现了破坏,从而不能获得期望利益。
本发明提供了这样的方法和系统,通过该方法和系统,在传递(mediate)SBE性态的软件中,与该软件的一个或多个部分Y不联锁的该软件的一个或多个部分X可以通过提供了一个或多个部分X的原始功能的一个或多个部分X′替代,该一个或多个部分X′与提供了一个或多个部分Y的原始功能的一个或多个部分Y′以下述方式联锁:X′和Y′的联锁方式是必要的、完整的、模糊的并且信赖上下文的。下面来描述所要求的有效联锁的这些属性以及用于实现这些属性的自动化方法。
参考表A,该表A包含整个文件中使用的符号及其含义。
表A
符号 含义
B 位的集合={0,1}
N 自然数的集合={1,2,3,...}
N0 有限基数的集合={0,1,2,...}
Z 整数的集合={...,-1,0,1,...}
x:-y 满足y的x
x iff y 当且仅当y
x‖y 数组或向量x和y的拼接
x∧y x和y的逻辑与或逐位与
x∨y x和y的逻辑同或或逐位同或
x⊕y x和y的逻辑异或或逐位异或
x-1 x的逆
f{S} 集合S在MF f下的像
f(x)=y 对x应用MF f得到且仅得到y
f(x)→y 对x应用MF f可以得到y
f(x)=⊥ 对x应用MF f的结果是未定义的
MT 矩阵M的转置
|S| 集合S的基数
|V| 数组或向量V的长度
|n| 数n的绝对值
(x1,...,xk) 具有元素x1,...,xk的k-数组或k-向量
[m1,...,mk] 多函数m1,...,mk的k-聚合
<m1,...,mk> 多函数m1,...,mk的k-群集(conglomeration)
{x1,...,xk} x1,...,xk的集合
{x|C} 满足C的x的集合
{x∈S|C} 集合S中满足C的元素x的集合
Δ(x,y) 从x到y的汉明距离(=所改变的元素位置的数量)
S1×...×Sk 集合S1,...,Sk的笛卡儿乘积
m1о...оmk 多函数m1,...,mk的复合(composition)
x∈S x是集合S的元素
集合S包含于或等于集合T
x1,...,xk的和
GF(n) 具有n个元素的伽罗瓦域(=有限域)
Z/(k) 整数以k为模的有限环
idS 集合S上的等同函数
extract[a,b](x) 位串x中位置a到b中的位字段
extract[a,b](v) (extract[a,b](v1),...,extract[a,b](vk)),
其中v=(v1,...,vk)
interleave(u,v) (u1‖v1,...,uk‖vk),其中u=(u1,...,uk)且v=(v1,...,vk)
表B还包含了该文档中使用的缩写及其意义。
表B
缩写 展开
AES 高级加密标准(Advanced Encryption Standard)
agg 聚合(aggregation)
API 应用程序接口(application procedural interface)
BA 布尔-算术(Boolean-arithmetic)
BB 基本块(basic block)
CFG 控制流图(control-flow graph)
DES 数据加密标准(Data Encryption Standard)
DG 有向图(directed graph)
dll 动态链接库(dynamically linked library)
GF 伽罗瓦域(=有限域)(Galois field(=finite field))
IA 间插聚合(intervening aggregation)
iff 当且仅当
MBA 布尔-算术混合(mixed Boolean-arithmetic)
MDS 最大距离可分的(maximum distance separable)
MF 多函数(multi-function)
OE 输出扩展(output extension)
PE 部分求值(partial evaluation)
PLPB 逐点线性分割双射
(point-wise linear partitioned bijection)
RSA 李维斯特-萨莫尔-阿德曼
RNS 余数系统(residual number system)
RPE 反向部分求值(reverse partial evaluation)
TR 防篡改性(tamper resistance)
SB 替换盒(substitution box)
SBE 基于软件的实体(software-based entity)
so 共享对象(shared object)
VHDL 超高速集成电路硬件描述语言
(very high speed integrated
circuit hardware description language)
用“:-”表示满足(such that)并且用“iff”表示“当且仅当”。表A总结了这里使用的许多符号,而表B总结了这里使用的许多缩写。
2.3.1.集合、数组、关系及函数。对于集合S,用|S|表示S的基数(即,集合S中元素的个数)。还用|n|表示数n的绝对值。
用{m1,m2,...,mk}表示元素为m1,m2,...,mk的集合。(这里,如果m1,m2,...,mk都不相同,则|{m1,m2,...,mk}|=k。)还用{x|C}表示使得满足条件C成立的形式x的全部实体的集合,其中C通常是取决于x的条件。
笛卡儿乘积、数组和向量。这里,A和B为集合,A×B为A和B的笛卡儿乘积,即,所有对(a,b)的集合,其中,a∈A(即,a为A的元素)并且b∈B(即,b为B的元素)。因此,可以得到(a,b)∈A×B。一般地,对于集合S1,S2,...,Sk,S1×S2...×Sk的元素为形式(s1,s2,...,sk)的k阶数组,其中si∈Si,i=1,2,...,k。如果t=(s1,...,sk)为数组,则用|t|表示t的长度(在这种情况下,|t|=k,即该数组具有k个元素位置)。对于任何x,认为x与(x)相同-具有唯一元素x的长度为1的数组。如果数组的全部元素都属于同一集合,则称其为该集合上的向量。如果u和v为两个数组,则u‖v为具有长度|u+|v|的数组,该数组是通过创建包含按照次序的u的元素然后按照次序的v的元素的数组所获得的,例如,(a,b,c,c,d)‖(x,y,z)=(a,b,c,d,x,y,z)。
在笛卡儿乘积中括号是非常重要的:对于集合A,B,C,(A×B)×C的元素看起来象((a,b),c),而A×(B×C)的元素看起来象(a,(b,c)),这里a∈A,b∈B并且c∈C。类似地,A×(B×B)×C的元素看起来象(a,(b1,b2),c),这里a∈A,b1,b2∈B并且c∈C。
关系、多函数(MF)及函数。对于k个阶集合(这里必须有k≥2)的笛卡儿乘积S1×...×Sk的k元关系为任何集合 通常,我们对二元关系感兴趣,即,对于两个集合A、B(不一定是不同的)的关系 对于这种二元关系,用a R b表示(a,b)∈R。例如,当R是实数集时,对于实数对的二元关系 为满足x小于y的全部实数对(x,y)的集合,而当时我们写出x<y时,它表示(x,y)∈<。
符号
表示
即,R为A×B上的二元关系。该符号类似于下述函数使用的符号。其目的是表示该二元关系解释为多函数(MF),计算的关系抽象(不一定是确定性的),其从集合A取输入,并返回集合B中的输出。在单个函数的情况下,该计算必须是确定性的,而在多函数的情况下,该计算不必是确定性的,因此对于外部事件可能影响给定处理内的执行进程的很多软件来说,这是一个较好的数学模型。A是MF R的定义域,而B是MF R的上域。对于任何集合
定义
R{X}为X在R下的像。对于
且a∈A,用R(a)=b表示R{{a}}={b},用R(a)→b表示b∈R{{a}},而用R(a)=⊥(读作“R(a)为未定义的”)表示不存在b∈B:-(a,b)∈R。
对于二元关系定义
R-1={(b,a)|(a,b)∈R}
R-1为R的逆。
SоR是S与R的复合。二元关系的复合是可结合的,即,对于二元关系Q、R、S,(SоR)оQ=Sо(RоQ)。因此对于二元关系R1,R2,...,Rk,可以自由书写不带括号的Rkо...оR2оR1,因为无论将括号放在哪里,该表达式意义都是相同的。注意
(Rkо...оR2оR1){X}=Rk{...{R2{R1{X}}}...}
其中,首先取X在R1下的像,然后取该像在R2下的像,如此这样,直到取倒数第二个像在Rk下的像,这就是在左边复合中的Ri以映像运算(imagingoperation)的逆序书写的原因,右边的映像表达式中的Ri也是如此。
在
i=1,...,k的情况下,R=[R
1,...,R
k]为二元关系:
并且
R(x1,...,xk)→(y1,...,yk),当且仅当(iff)Ri(xi)→yi,i=1,...,k。
[R1,...,Rk]为R1,...,Rk的聚合。
在
i=1,...,n的情况下,R=<R
1,...,R
n>为二元关系:
并且
R(x1,...,xm)→(y1,...,yn),当且仅当(iff)Ri(x1,...,xm)→yi,i=1,...,n。<R1,...,Rk>为R1,...,Rk的群集。
用
表示f是从A到B的函数,即,
满足:对于任何a∈A和b∈B,如果f(a)→b,则f(a)=b。对于任何集合S,id
S是这样的函数,对于各x∈S,id
S(x)=x。
有向图、控制流图和支配点(Dominator)。有向图(DG)是有序对G=(N,A),其中,集合N为节点集,且二元关系 是弧关系(arc-relation)或者边关系(edge-relation)。(x,y)∈A是G的弧或边。
在DG G=(N,A)中的路径是节点序列(n1,...,nk),这里ni∈N,i=1,...,k,并且(ni,ni+1)∈A,i=1,...,k-1。k-1≥0是路径长度。最短的可能路径是具有长度为零的形式(n1)。当且仅当(iff)在路径(n1,...,nk)中没有节点出现两次时,即当且仅当(iff)不存在索引i,j,在1≤i<j≤k时ni=nj,该路径(n1,...,nk)是非循环的(acyclic)。
对于集合S,定义Sr=S×...×S,这里S出现r次,而×出现r-1次(从而S1=S),并且定义S+=S1∪S2∪S3∪...-对于所有可能长度的S的全部笛卡儿乘积的无限并集。则C中各路径为N+的元素。
在有向图(DG)G=(N,A)中,如果在G中存在起点为x终点为y的路径,则节点y∈N是从节点x∈N可达的。(因此各节点从自身都是可达的。)N中节点x的到达范围是从x可达的节点的集合。当且仅当(iff)以下两个条件之一递归地成立时,在G中两个节点x,y才是连通的:
·G中存在x和y都出现的路径,或者
·在G中存在节点z∈N,使得x和z是连通的,并且y和z是连通的。(如果x=y,则单元素(即,长度为1)路径(x)是从x到y的路径,因此G的各节点n∈N对于其本身是连通的。)当且仅当(iff)DG G=(N,A)的每对节点x,y∈N是连通的时,DG G=(N,A)为连通DG。
对于各节点x∈N,在A中从x开始在其他某节点结束的弧的数量|{y|(x,y)∈A}|为节点x的出度(out-degree),并且对于各节点y∈N,在A中从某节点开始在y处结束的弧的数量|{x|(x,y)∈A}|为节点y的入度(in-degree)。节点n∈N的度(degree)为n的入度和出度之和。
DG G=(N,A)中的源(source)节点为入度为零的节点,而DG G=(N,A)中的汇(sink)节点为出度为零的节点。
当且仅当(iff)DG G=(N,A)具有可达各节点n∈N的奇异源节点(distinguished source code)n0∈N时,该DG G=(N,A)为控制流图(control-flow graph(CFG))。
设G=(N,A)为具有源节点n0的CFG。当且仅当(iff)从n0开始到y结束的各路径都包含x时,节点x∈N支配(dominate)节点y∈N。(注意,通过该定义及上述论述,各节点都支配其自身。)
具有上述G=(N,A)和s,当且仅当从n0开始以Y的元素结束的各路径都包含X的元素时,非空节点集合 支配非空节点集合 (注意,单节点支配另一单节点的情况是该定义在|X|=|Y|=1时的特殊情况。)
2.3.2代数结构。Z表示所有整数的集合,而N表示所有大于零的整数(自然数)的集合。Z/(m)表示对于某整数m>0,整数以m为模的环。只要m是素数,就有Z/(m)=GF(m),即整数以m为模的伽罗瓦域。B表示位的集{0,1},其可以利用两个元素的环Z/(2)=GF(2)来标识。
恒等式。恒等式(即,方程)在模糊化中起着关键作用:如果对于两个表达式X,Y,已知X=Y,则可以用Y的值替代X的值,并且可以用Y的计算替代X的计算,反之亦然。
通过在[2、4、5、7、8、9、17、18、19、20、23、24、27]的每个中不同程度地找到它们的使用的事实可以看出,这种基于代数恒等式的替换对模糊化是至关重要的。
有时希望将本身涉及方程的布尔表达式进行等同(使相等)。例如,在典型计算机算术中,
x=0 iff(-(x∨(-x))-1)<0
(利用带符号的比较)。因此,“iff”等同于条件,从而包含“iff”的该表达式也是恒等式,特别是条件恒等式或布尔恒等式。
矩阵通过下式表示r×c(r行,c列)的矩阵M
这里用MT表示其转置矩阵,
因此,例如
Z/(2n)与计算机算术的关系。对于所有长度n的位向量的集合Bn,利用2的补码定点运算照常定义用于计算机的加法(+)和乘法(·)(见[21])。则(Bn,+,·)为2n阶的有限2的补码环。模整数环Z/(2n)为(Bn,+,·)的同构,这是在具有n位字长的计算机上的典型计算机定点计算(加法、减法、乘法、除法和求余)的基础。
为方便起见,用xy表示x·y(x乘y),即,通过在代数学中作为通用惯例的并置来表示乘法。
从该同构来看,即使将(Bn,+,·)看作包含在-2n-1到2n-1-1(包含端点)范围内的带符号数,也可交换地利用这两个环。能够忽略(Bn,+,·)的元素是占用了上述带符号范围还是从0到2n-1(包含端点)的量值范围的问题的原因是对Bn中的位向量的算术运算“+”和“·”的效果是相同的,不管将该数解释为2的补码带符号数还是二进制量值无符号数。
将该数是否解释为带符号的问题仅仅对于不等式算子<、>、≤、≥才出现,这意味着应当提前决定如何处理具体数:正如通过C或C++编译器不正确地使用带符号和不带符号的比较指令将会产生异常代码一样,不一致的解释会产生异常结果。
逐位计算机指令和
对于所有长度n的位向量的集合B
n,具有n位字的计算机通常提供了逐位与(∧)、同或(∨)和非
则
为布尔代数。在
中,向量长度为一,0为假而1为真。
表C
合取 二进制 结果
110 1
对于任意两个向量u,v∈B
n,通过
来定义u和v的逐位异或(⊕)。为方便起见,通常用
表示
例如,也可以将该恒等式表述为
由于在布尔代数中向量乘法(逐位与(∧))是可结合的,因此(Bn,⊕,∧)为环(称为布尔环)。
真值表。为使得
上的表达式的值直观,可以使用如表C中所示的真值表。该表使表达式
对于x,y,z全部可能的布尔值(B的元素)变得直观。在最左列中,标题为“合取”,通过仅仅给出各变量以值为真(即,1)的正常(v)或者补
形式恰好出现一次的“与”(合取)来呈现出x,y,z的各种状态。在中间列中,标题为“二进制”,将同样信息显示为二进制数,使从左到右的各位表示从左到右的各变量的值。在右列中,标题为“结果”,示出了用具体值替换表达式
中各变量的结果。例如,如果
为真(即,1),则x,y,z的值分别为011,而
乘法逆元素和逆矩阵的存在与否。对于任何素数幂,当在GF(m)中,各元素都具有乘法逆元素(即,对于各x∈{0,1,...,m-1},存在y∈{0,1,...,m-1}满足x·y=1),对于任意k∈N,Z/(k)通常不是这样的,即使k是素数幂也不是这样。例如,在Z/(2n),n∈N且n>1时,没有偶元素具有乘法逆元素,因为当乘以偶元素时不存在能够得到奇数1的元素。此外,两个非零元素的积可以是零。例如,在Z/(23)上,2·4=0,因为8 mod 8=0。作为该环属性的结果,Z/(2n)上的矩阵具有非零行列式,并且仍然不具有逆。例如,矩阵
对于任意n∈N,在Z/(2n)上是不可逆的,虽然其行列式为2。当且仅当(iff)Z/(2n)上的矩阵的行列式是奇数时,该矩阵才是可逆的。
Z/(2n)形式的环上的矩阵的另一重要属性是这样的。如果矩阵M在Z/(2m)上是可逆的,则对于任何整数n>m,如果通过在该元素的二进制表示的开头添加n-m个“0”位来创建新的矩阵N,由此将其值保留为二进制数,但“字长”从m位增大到n位,则N在Z/(2n)上是可逆的。(因为当计算该行列式时增加计算的字长度不会影响奇偶性)。
通常,我们不会明确提及如上所述从M导出分离矩阵N的推导。相反,对于如上所述在Z/(2m)上的矩阵M,简单地称为“Z/(2n)上的”M,其目的在于现在考虑通过增加M的元素的“字长”而推导出的矩阵N;即,有效地忽略M的元素数组的长度,并简单认为M的元素是整数值。因此,当提到“Z/(2n)上的”M时,有效地表示已修改成具有某字(数组)大小的M是适合于域Z/(2n)的。
将算术系统和逐位系统组合。通过组合代数系统(B
n,+,·)(阶数2
n的2的补码环)和
(在逐位与、同或及非下长度为n的位向量的布尔代数)获得的单个系统
称为布尔算术代数(BA代数),并且用BA[n]表示长度为n的位向量上的该具体ba代数。
BA[1]是特殊情况,因为+和⊕在该BA代数中是等同的(⊕有时称为“无进位加法”,而在BA[1]中该向量长度为1,因此+不会受到进位位的影响)。
注意到,在Z/(2n)中的u-v=u+(-v),并且 (v的2的补码),这里1表示向量(0,0,...,0,1)∈Bn(即,二进制数00...01∈Bn)。因此二元的+,-,·运算和一元的-(非)运算是Z/(2n)的所有部分。
如果BA[n]上的表达式包含来自Z/(2
n)的运算+、-、·和来自
的运算二者,则称其为布尔-算术混合表达式(MBA表达式)。例如,“(8234x)∨y”和
为MBA表达式,其可以在C,C++或者Java
TM中分别写成“8234*x|~x”和“~x+(y*z & x)”。(通常,程序语言中的完整算术表达式是在BA[32]上实现的,例如,对于大多数个人计算机,趋势是增加BA[64]的使用,例如Intel Itanium
TM。)
如果BA[n]上的表达式E具有形式
这里c1,c2,...,ck∈Bn并且e1,e2,...,ek是上的变量集的表达式,则称E为线性MBA表达式。
多项式。多项式为以下形式的表达式 (这里,对于任何x,x0=1)。如果ad≠0,则d为多项式的次数(degree)。可以对多项式进行加、减、乘、除,并且这种运算的结果本身也是多项式。如果d=0,则多项式为常量,即,它仅由标量常量a0构成。如果d>0,则多项式为非常量。可以有在有限和无限环及域上的多项式。
如果非常量多项式不能写成两个或者更多个非常量多项式的积,则它是不可约的。不可约的多项式对多项式所起的作用类似于素数对整数所起的作用。
变量x没有特殊意义:对于具体多项式,它只是一个位置保持器(place-holder)。当然,可以用一个值替代x以对多项式进行求值,即,变量x意义仅在于用某物替代它。
可以用多项式的系数(d+1)-向量(ad,...,a1,a0)来标识多项式。
GF(2)=Z/(2)上的多项式在密码学中具有特殊的意义,因为系数的(d+1)-向量只是位串,并且能够在计算机上有效地表示(例如,次数达到7的多项式可以用8位字节表示);加法和减法是等同的;并且可以利用逐位⊕(异或)来计算两个这样的用位串表示的多项式的和。
有限域。对于任何素数p,Z/(p)不仅是求模整数环,而且是求模整数域。这与单纯的有限环的区别在于每个元素都有唯一的逆。
这种域中的计算是不方便的,因为需要在计算机上进行很多求余运算以将结果限制于该模数,并且这种运算很慢。
对于任何素数p和整数n≥1,存在具有个pn个元素的域,表示为GF(pn)。该域可以利用以n次不可约多项式为模数执行的多项式计算由模环Z/(p)上的0到n-1次(包括端点)多项式生成。这种域对于p=2的情况在计算机上计算时变得更容易处理,从而多项式可以表示为位串,而加法/减法表示为逐位⊕。例如,高级加密标准(AES)[15]是基于GF(28)上的计算。由于在GF(2n)上线性的函数在GF(2)上也是线性的原因,使得GF(2n)上的矩阵运算便利得多,即,它们可以利用位矩阵来计算。实际上,每台现代计算机都是针对可达机器字长度(通常为32或者64)的位向量的“向量机”,这便于基于这种位矩阵进行计算。
2.3.3.部分求值(PE)。尽管部分求值不是创建用于将保护绑定至SBE的通用、低开销、有效联锁所必需的,但是部分求值与本发明的方法极为相关,并且理解了部分求值有助于理解这些方法。
MF的部分求值(PE)通过冻结一些其他MF的一些输入来生成MF(或者这样生成的MF)。更正式的是,设
为MF。针对常量c∈Y,f的部分求值(PE)是下述的推导:
满足对于任何x∈X和z∈Z,g(x)→z iff f(x,c)→z。为了表示该PE关系,还可以写成g(·)≡f(·,c)。还可以将通过f的PE推导出的MF g称为f的部分求值(PE)。即,术语部分求值可以用于指代推导过程或者其结果。
在软件中在SBE及其保护的环境中,上述f和g是程序,而x,c为程序输入,并且,更具体的程序g是基于f最右边的一个或多个输入为常量c的假设通过f中的预求值计算从较通用的程序f推导出的。x,c可以包含任何数量的信息。
为了提供具体示例,来考虑编译的情况。在没有PE的情况下,对于编译器程序p,具有
这里S是所有源代码文件的集合,而E是目标代码文件的集合。则e=p(s)可以表示将编译器程序p应用于源代码文件s,得到目标代码文件e。(取p为一个函数,而不仅仅是多函数,因为通常希望编译器是确定性的。)
现在假设有一个非常通用的编译器为q,其输入有源程序s及语义描述对:源语言语义描述d及在期望目标平台上的可执行代码的语义描述t。它根据源语言语义描述将源程序编译成针对期望目标平台的可执行代码。然后具有
这里S是源代码文件的集合,D是源语义描述的集合,T是平台可执行代码语义描述的集合,而E是针对任何平台的目标代码文件的集合。然后,专用编译器是q相对于常量数组(d,t)∈D×T(即由特定源语言语义描述和特定目标平台语义描述构成的对)的PE p:即对于一些特定的常量(d,t)∈D×T,p(s)=q(s,(d,t))。在这种情况下,X(PE保留的输入集合)是S(源代码文件的集合),Y(PE通过选择其特定元素来移除的输入集合)是D×T(源语义描述的集合D和目标平台语义描述的集合T的笛卡儿乘积),而Z(输出集合)为E(目标代码文件的集合)。
PE用于[7、8]中:参照密钥,对AES-128加密器[15]和DES加密器[12]进行部分求值,以便对攻击者隐藏密钥。[17、18]中对基本方法和系统给出了更详细的描述。
当优化编译器在它们通过下述方式用更具体的计算来代替一般计算时执行PE:确定在运行时间在何处操作数将是常量,然后将它们的运算用常量或者不再需要输入(有效常量)操作数的更具体的运算来替代。
2.3.4.输出扩展(OE)。假设具有函数
当且仅当对于每个u∈U时有g(u)=(f(u),w),其中一些w∈W,函数
是f的输出扩展(OE)。即,g给出f实现的一切,并且另外产生额外的输出信息。
还可以使用术语输出扩展(OE)表示给定该函数f找出这种函数g的过程。
当函数f实现为例程或其他程序片段时,通常直接确定实现函数g(其为函数f的OE)的例程或程序片段,因为找出这样的函数g的问题是非常松约束的。
2.3.5.反向部分求值(RPE)。为创建了用于将保护绑定到SBE的一般性、低开销、有效联锁,采用了基于反向部分求值(RPE)的新方法。
简单地说,对于大多数任何MF或者程序
存在程序或MFf、集合Y和常量c∈Y的极大集合,对此,对于任意x∈X,总有g(x)=f(x,c)。
将找出这种数组(f,c,Y)的过程(或者通过该过程找出的数组)称为g的反向部分求值(RPE)。
注意,PE倾向为具体的并且是确定性,而RPE提供了无限大数量的备选对象:对于给定g,可以存在任意数量的不同数组(f,c,Y),每个数组都有资格作为g的一个RPE。
找出作为更一般的程序的PE的有效程序可能非常难,即,该问题是非常紧约束的。找出给定具体程序的有效RPE通常是非常容易的,因为有如此多的正规选择,即,该问题是非常松约束的。
2.3.6.代码编译中的控制流图(CFG)。在编译器中,通常通过控制流图(CFG)来表示通过程序的可能控制流,其中,可执行代码的基本块(BB:basic block)(具有单起点、单终点并且从其起点到其终点是顺序地执行的“直线”代码序列)由图形节点表示,并且如果在包含程序的执行期间控制或者总是或者可能从BB U的终点流至BB V的起点,则用弧将对应于BBU的节点连接到对应于BB V的节点。这可以以多种方式发生:
(1)·控制流可以自然地从BB U进行到BB V。
例如,在下述C代码段中,控制流自然地从U进行到V:
switch(radix){
case HEX:
U
case OCT:
V
}
(2)·控制流可以通过诸如while循环、if语句或goto语句的内部程序控制结构从U引导至V。
例如,在以下C代码段中,控制通过break语句从A引导至Z:
switch(radix){
case HEX:
A
break;
case OCT:
B
}
Z
(3)·控制流可以通过调用或返回从U引导至V。
例如,在以下C代码段中,控制通过在g()主体内对f()的调用从B引导至A,并通过从对f()调用的返回从A引导至C:
void f(void){
A
return;
}
int g(int a,float x){
B
f();
C
}
(4)·控制流可以通过例外控制流事件从U引导至V。
例如,在下述C++代码段中,控制可以通过比如引用y的dynamic_cast未能引用到类A中的对象潜在地从U引导至V:
#include<typeinfo>
int g(int a,float x){
try{
U
A& x=dynamic_cast<A&>(y);
catch(bad_cast c){
V
}
}
对于CFG C=(N,T)中的各节点n∈N(C代表控制,T表示传递),节点n用来表示具体BB,并且该BB计算通过BB n包含的代码确定的mf:某个函数
这里X表示通过n的代码所有可能读取和使用的值(以及由此对函数f的输入)的集合,而Y表示通过n的代码所有可能写出的值(以及由此来自函数f的输出)的集合。通常f为函数,而如果f利用诸如高分辨率硬件时钟的当前读数的非确定性输入,则f为MF而非一个函数。此外,某计算机硬件包括会产生非确定性结果的指令,这又导致f为MF,而非一个函数。
对于具有CFG C=(N,T)和起始节点n0的整个程序,使N等同于程序的BB集合,使n0等同于在该程序起点处出现的BB(通常对于C或C++程序,是例程main()的起始BB),并且将T等同于从该程序的一个BB到另一个BB的控制的每一个可行传递。
有时,替代整个程序的CFG,可以具有单个例程的CFG。在这种情况下,使N等同于该例程的BB的集合,将n0等同于在该例程的起点处出现的BB,并且将T等同于从该例程的一个BB到另一个BB的控制的每一个可能传递。
2.3.7.CFG的替代解释。在§2.3.6中,讨论了控制流图(CFG)的标准的面向编译器的视图。然而,通过CFG表示的子计算中的关系可以其他方式发生。
例如,CFG C=(N,T)可以表示计算的一段(slice),其中,一段是计算中与输入和/或变量和/或输出的特定子集相关的一部分。将一段的概念用于程序的目标导向的分析中,其中,全部程序的分析可能会消耗过多资源,但如果将注意力仅仅集中于计算的一部分,则对该部分进行更深入分析是可行的。
具体地说,具有多处理甚至是分布式并行程序C=(N,T),在该程序C=(N,T)中相对于计算的一段出现CFG C=(N,T),其中,并行程序中仅有一些BB包含在N中(即, ),而T表示当忽略在C中但不在其子集C中的计算时在N的元素之间的执行流。即,单处理非并行程序C可以被嵌入更大的并行程序C中,使得C占用多于一个的处理,但相对于N的元素中的计算来说,因为由C强加的消息约束或者其他约束,该计算是有效地顺序的。
只要满足本发明的控制流要求,本发明的所有方法都可以等同地应用于具有自然的、单处理的控制方法的程序以及应用于较大、包含、并行程序的一段。我们开发了CFG的该替代视图来实现§2.10.6的方法。
此外,BB内的代码以指示计算机改变其状态的一系列计算机指令实现。通常,指令影响该状态的一小部分,而使该状态的其余部分保持不动。BB也可以包括例程。例程本身包括CFG,并且构造成允许该CFG通过传递到其状态(变元)的例程初始部分的调用来执行,同时执行在调用之后立即返回。
可以将例程看作标准控制流的一部分(详细视图),或者可以从详细图提取并将例程调用当作一类“超级指令”,该超级指令使得计算机执行比普通计算机指令更复杂的状态改变。
两种视图关于本发明都是有用的,可以选择对于特定目的来说特定调用的哪一种视图更方便。因此,当提及程序的CFG时,意思是指已经应用了所选择的提取形式之后的CFG。此外,可以通过对不同联锁应用同一例程调用的不同视图来将本发明应用于程序的不同方面的联锁。
2.4.联锁的关系和计算结构。在SBE的直接构造中,常常存在自然的完全没有联锁的部分,即存在其运行使得与其它部分彼此独立的部分。为了保护SBE的特定性态,可能包括添加到SBE的特定保护性的性态,必须确保SBE的实现该特定性态的那些部分绝不是这样的情况。因此,必需找到在SBE性态下计算中初始时相互独立的部分,并使他们变成相互依赖。
本发明描述了一种基于MF的部分求值(PE)、MF的输出扩展(OE)、MF的反向部分求值(RPE)、以及在控制流图中的支配节点和集合的概念的技术。
2.4.1.联锁的关系结构。图1中示出了联锁的最小关系结构。在图1中,示出了通过计算连接的初始程序状态和最终程序状态。从A状态到B状态的上路径表示普通的、未编码或者未模糊化的计算,而从状态A′到状态B′的下路径表示从经编码或者被模糊化的状态A′(状态s的模糊)到经编码或者被模糊的状态B′(状态B的模糊)的经编码或者被模糊化的计算(“′”表示经修改的实体:输入-输出经编码、输入经编码或者输出经编码的MF,或者经编码后的数据状态)。R′表示传递MF:其载有从状态A′到状态B′的联锁信息。
在该最小结构中,R是原始计算,将计算状态a∈A变换到状态b∈B。(R不需要是确定性的。)R′是根据本发明已修改后的计算。R′是修改后的计算,将扩展状态a′∈A′变换到扩展状态b′∈B′。通过扩展,意思是a′和b′分别包含a和b中的全部信息以及附加信息。附加信息可以用于确定是(1)b′是从对a′的预定计算R′得到的,还是(2)b′是从被攻击者已修改过的代码和/或从由于攻击者的篡改而代替a′的修改后的数据得到的。联锁的本质核心是该额外信息以及为了正确性可以检查该额外信息这一事实。
通常,还存在根据本发明的将提供附加初始计算以在开始时创建额外信息的进一步修改,并且还存在将提供附加最终计算以消耗该额外信息的进一步修改,并且取决于最终状态的合法性,如果是合法的则此后计算将正常进行,而如果是不合法的,则计算很可能将失败。
如果所有的R、R′、d、d-1、r、r-1不仅仅是关系,而是函数,则图1会是用于计算加密函数的交换图表,如[23、24]中所提出。(在分类理论中,这种图表用于表示函数之间的关系,使得图表中从一个节点到另一个节点的不同路径是等同的,例如图表将指出R′=cоRоd-1。)
然而,对于我们的目的来说这是不够的。第一,联锁作为被保护代码在保护不足的代码环境中运行。因此,图表仅示出了计算中具体的、受保护的部分。(图2中示出了更典型的设置,其具有相同的内部结构。)
其次,产生必要的、完整的、模糊的并且依赖上下文的(这些属性在下面定义)联锁需要更强有力的方法。不要求R、R′、d、d
-1、r、r
-1是函数,但要通过对R、R′、d、d
-1、r、r
-1施加强要求来确保上述关键属性。因此图1中的箭头表示MF。例如,从A到A′的箭头表示
即
因此,可能不存在唯一的对应于具体a∈A的a′∈A′。
图1示出了通过计算连接的初始和最终程序状态。该图表应用于孤立地运行的联锁,其中在出现联锁之前没有重要数据状态,并且在其后也没有重要数据状态,即,这种联锁通过从图2中所示的联锁结构中进行省略而推导出:在其他地方计算出联锁的(联锁-信息-)产生代码F′和联锁的(联锁-信息-)消耗代码,联锁的(联锁-信息-)产生代码F′从某正常起始状态P建立(联锁-信息-)所产生的状态A′,并将该状态转换到A′,并且联锁的(联锁-信息-)消耗代码将(联锁-信息-)所传递的状态B′转换到某正常结束状态E。例如,图1可以应用于网络中的事务处理程序的情况,在网络中,(联锁-信息-)传递代码
处理由正常未经保护的预传递(即,预-联锁-信息-传递)计算
推导出的事务,但不建立联锁的所产生的状态A′,在达到联锁的所传递的状态B′之后也不恢复正常计算-如果在状态A′和状态B″(由篡改所导致的B′的非标准变型)之间发生篡改也不导致计算失败。在这种联锁的这种删减版中,行为是在其他某处发生的“私下行为”,并且只出现联锁的传递部分,即计算
该图示出了:对于攻击者可见的起始状态A′(根据定义域编码d由A得到的)、将状态A′转换到状态B′的计算R′以及结束状态B′(根据上域编码c由B得到的)。状态A(当没有引入联锁时的起始数据状态)、计算R(当没有引入联锁时会将A转换到B的计算)以及结束状态B(当没有引入联锁时的结束数据状态)对攻击者是不可用的,因为它们已经通过将联锁插入到程序被消除。注意:实际孤立的联锁计算是R′。计算R、d、d-1、r、r-1和状态A、B在最终的实现中并不存在;仅在基于非联锁计算R构建联锁计算R′期间使用它们。
图2示出了典型联锁情况下与图1完全相同的内部结构,这里通过下述方式来对沿着下路径的执行进行联锁:将执行从在某先前状态P处的A到B路径转向经编码或者被模糊化的A′到B′路径,然后返回到在某未经编码或未被模糊化的结束了该联锁的结束状态E处的正常、未经编码或未被模糊化的计算。图2中的情形是典型的联锁情形,然而,在将联锁引入代码之前,存在先前的起始状态P,通过预产生(即,预-联锁-信息-产生)计算F′转换到所预产生(即,预-联锁-信息-产生)状态A,该状态A又通过预传递计算R被转换到所预传递(即,预-联锁-信息-传递的)状态B,然后,该状态B又通过预消耗(即,预-联锁-信息-消耗)计算G转换到结束状态E。已经选择了联锁A和B。在引入联锁之后,从起始状态P开始,通过产生计算F′将其转换到所产生的状态A′,这里A通过定义域编码关系d与A′相关,通过传递计算R′将A′转换到所传递的状态B′,这里B通过上域编码c与B′相关,以及通过消耗计算G′将B′转换到结束状态E。(联锁信息的产生使得其进入可以使用的状态,而联锁信息的消耗则使用该信息,并且如果没有篡改的干涉就会正常起作用,或者如果在操作中发生篡改干扰就会出现故障。)攻击者仅能够访问已经插入了联锁后的程序,即,攻击者仅能够看到状态P、A′、B′、E和计算F′、R′、G′。原始状态A、B,计算F、R、G,在A和A′之间的关系d以及在B和B′之间的关系c在安装了联锁的程序最终版本中消失了。注意:安装后的联锁的组件是产生F′、所产生的状态A′、传递R′、所传递的状态B′以及消耗G′。在安装联锁之前的相应部件通过添加前缀“预”来命名,以表示还没有进行联锁安装修改:预产生F、预产生状态A、预传递R、预传递状态B和预消耗G。起始状态P和结束状态E既出现在安装联锁之前也出现在安装联锁之后。
通过输出扩展(OE)由F得到F′。创建F的输出扩展
即,通过输出扩展修改F以计算额外信息J。然后对A x J进行编码,即,得到编码A′=(A x J)′,这里“′”表示经修改的或者经编码的实体。然后修改F
OE以获得:
因此,F′是原始F的OE FOE的经编码的版本。
是通过聚合由
得到的。介于A和B之间的原始计算,即
必须由能够从A′带到B′的计算来代替。首先,注意A′=(A×J)′。选择具有不会从J丢失信息的属性的MF(计算)
即,S
-1оS为关于J的恒等函数(对于任何MF M,很可能M
-1оM甚至都不是函数,更不用说是恒等函数),使得对于任何x∈J都有(S
-1оS)(x)=x。
保留信息。在计算机算术以及有限环及域中不丢失信息的函数是公知的。例如,加上常量c不丢失信息(原始信息可以通过减去c来恢复);与c异或不丢失信息(原始信息可以通过与c进行第二次异或来恢复),在有限域或环上与非奇异(即,可逆)矩阵相乘不丢失信息(原始信息可以通过乘以其逆矩阵来恢复),对向量应用深度非线性双射函数(这里该函数是根据在方案:利用宽输入深度非线性函数中描述的方法实现的)不丢失信息(原始向量可以通过应用按照在所构造的深度非线性函数的求逆中的描述得到的那个函数的逆重新得到)。精通计算机算术和大代数属性的任何人都可以获得这种函数的宽选择范围。
定义
并且输入输出编码Ragg,即联锁的间插聚集(IA),这里按照上述构建信息保留MF S来保留信息,以获得
这里A′=(A x J)′,B′=(B x K)′并且R′=Ragg′=[R,S]′通过反向部分求值(RPE)由G得到G′。创建G的RPE
然后对GRPE和B×K进行编码,这里B×K的编码是创建R′时选择的编码。通过对GRPE进行编码,获得
这里B′=(B×K)′并且G′=G′
RPE。从而,G′是原始G的RPE G
RPE的经编码的版本。
注意:实际联锁的计算是R′、F、R、G、d、d-1、r、r-1,并且状态A、B在最后的实现中并不存在,它们仅在构造联锁产生计算F′、基于非联锁计算R的联锁计算R′以及联锁结束计算G′期间使用;联锁产生计算F′将状态从未被联锁插入所修改的P转换至建立了联锁依赖性的状态A′;联锁计算R′是将联锁依赖性从状态A′带到状态B′的计算;联锁结束计算G′使状态从B′转换回未被联锁的插入所修改的联锁结束状态E。
2.4.2.联锁的计算结构。设W为程序或者较大程序内的例程,这里W具有起始节点(即起始BB)n0∈N的控制流图W=(N,T),而N为W的BB的集合,并且T为W中从W的一个BB的终点到W的另一个BB的起点的任何执行中的可能控制传递的集合。
表D中示出了关系视图的元素和计算视图的元素之间的对应关系。
表D-联锁的关系视图和计算视图
设BB集合
(预产生BB)支配BB集合
(预消耗BB),其中
X={x
1,...,x
m},并且Y=(y
1,...,y
n},这里
·在W中没有从n0开始的非循环路径在多于一个位置上具有X的元素,并且
·在W中没有从n0开始的非循环路径在多于一个位置上具有Y的元素,
使得X中的BB彼此为严格择一(strict alternative),而Y中的BB也彼此为严格择一。
设x
i计算关系
i=1,...,m,并设y
i计算关系
i=1,...,n。(在联锁的实际插入中,通常具有|X|=|Y|=1,但存在对创建BB的更大集合之间的联锁有用的情形。)
在X中预产生BB和Y中预消耗BB之间的路径上存在V={v
1,...,v
k}中的零个或更多个预传递BB。V中的间插BB计算预传递
(并且如果V为空,则A=B并且R=id
A)。对于任意给定x
i∈X,y
j∈Y,存在路径p
1,...,p
k∈V
+的集合,这里各该路径p具有形式(v
α,v
β,v
γ,...,v
ω),并且
·(xi,vα,vβ,vγ,...,vω,yj)为C中的路径,
·(v
α,v
β,v
γ,...,v
ω)计算
这里
·r=rωо...оrγоrβоrα,以及
·vi计算ri,i=α,β,γ,...,ω,使得沿路径(vα,...,vω)逐步地计算出r,这是大家可以自然想到的。
图3中示出了通过这些BB集合的可能路径,其示出了通过BB集合一条路径,即预联锁。(后联锁,该路径是类似的,但替代X、V、Y、x1,x2,x3,...,xi,...,xm、vα,vβ,vγ,...,vω、y1,y2,y3,...,yj,...,yn,BB集合和BB标记将是X′、V′、Y′、x1′,x2′,x3′,...,xi′,...,xm′、vα′,vβ′,vγ′,...,vω′、y1′,y2′,y3′,...,yj′,...,yn′。)图3示出了通过某些基本块集合的路径,提供了诸如图2中的计算的替代视图,这里,控制流过初始设置X(示出为图2中的状态P到状态A′的路径),流过经编码或被模糊的计算V(示出为图2中的状态A′到状态B′的路径),并最后流过恢复为常态的计算Y(示出为图2中B′到E的路径)。在图3中,可以看到控制在BB xi处进入联锁区域,由此控制传递给vα,然后传递给vβ,再传递给vγ,然后通过图中未示出的某些传递的序列,最终到达vω,由此控制传递到yj,然后传递出联锁区域。
这里假设如在下述状态中的状态信息包括程序计数器信息:起始状态P1,...,Pm、所预产生的状态A1,...,Am、所产生的状态A1′,...,Am′、所预传递的状态B1,...,Bn、所传递的状态B1′,...,Bn′和结束状态E1,...,En,即,程序中的当前执行位置与状态相关联。然后,就图2来说,具有P=P1∪...∪Pm,A=A1∪...∪Am,F=f1∪...∪fm,B=B1∪...∪Bn,G=g1∪...∪gn并且E=E1∪...∪En。在状态信息中包括程序计数器信息确保:对于作为从位置和寄存器标识符队列到它们的对应数据内容(包括当前程序计算器,即当前执行位置)的映射集合的状态信息的合理数学解释来说,这些并集是明确的。
为了创建从BB集合X到BB集合Y的联锁,修改程序或例程W,创建程序(或例程)W′,其中,按如下方式来修改X的BB、V的BB以及Y的BB。
通常存在由BB V={v1,...,vk}执行的计算(因为传递计算将被插入这些BB中,所以称为预传递计算),形成BB集合V,该BB集合V插在X和Y之间的路径上。对应于V,创建替换V的那些BB的传递BB的集合V′,传递BB的集合V′将由X′(产生BB)计算出的输出扩展F′(产生)的信息携带到由Y′(消耗BB)计算出的RPE G′(消耗)。即,V中的BB执行未修改的程序中的计算R,并且,在安装了联锁的情况下,V的替换集合V′中的BB(传递BB)执行计算R′(传递)。
对于计算关系
的各BB x
i∈X,将其修改成计算关系
的BB x′
i,这里A
i′=(A
i×J)′,fi′=F
OE,i′,并且
为f
i的输出扩展。
对于各BB路径,在C中(v
α,...,v
ω)插x
i和y
j之间(使得(x
i,y
α,...,v
ω,y
j)为C中的路径),这里(v
α,...,v
ω)计算某
修改V中的BB,使得路径被计算某
的新路径v
α′,...,v
ω′替代,这里
A
i′=(A
i×J)′,B
j′=(B
j×K),r′=r
agg′,
r
agg=[r
i,j,s
i,j],r
agg的并集为R
agg,r
i,j的并集为R,s
i,j的并集为S,而R
agg=[R,S]为原始R与MF S的聚合,如以上§2.4.1中所述。而且,如上所述,沿原来为(v
α,...,v
ω)并最终为(v′α,...,v′ω)的路径逐步地计算r
i,j和s
i,j。
对于计算关系
的各BB y
j∈Y
j,将其修改成计算关系
的BB y
j′,这里B
j′=B
j×K,g
j′=g′
RPEj,并且
是具有这样的属性的g
j的输出扩展,即,对于由f
OE,i输出的各值x∈J,作为正确输入提供给g
RPE,j的对应y∈K使g
RPE,j(·,y)与g
j(·)等同。
称X的替代为BB X′,V的替代为BB V′,而Y的替代为BB Y′。则W′包含X′、V′和Y′,而W包含X、V和Y。由X′替代X、由V′替代V和由Y′替代Y的上述形式(将W转换为W′)是安装已经创建的从X的功能性到Y的功能性的联锁,这防止了会破坏A′和B′之间的相关数据链接的篡改。
就图2而言,BB X执行计算F,BB Y执行计算G,BB X′执行计算F′,BB Y′执行计算G′,BB V执行计算R,并且BB V′执行计算R′。
在W′的执行过程中,当遇到任意yj′∈Y′BB时,控制通过透过某xi′∈X′BB到达y′j,因为X′支配Y′。当执行x′i时,计算fi′而不是fi,产生被编码成Ai′的某额外信息s∈J。控制通过计算R′的某路径(v1′,...,vz′)到达计算g′j的y′j,R′将该额外信息s∈J转换成以B′j编码的额外信息t∈K。y′j是只有该信息达到y′j而在X′或V′中未发生篡改时才正确地计算g′j的RPE。
如果t的内容由于攻击者篡改了在X′中的或者在X′中的BB与Y′中的BB之间的代码或数据而被修改,则不是计算编码版本的gOE,j(c,t),而y′j计算编码版本的gOE,j(c,u),其中某值u≠t。这导致G′计算以下述各种方式中的一种失效。当在联锁的原始创建中已经确保了gj′(c,e)=gj(c),求模编码和RPE,如果已经良好地构造了X′和Y′BB,则几乎可以确定具有gj′(c,t′)≠gj(c),实际上,已经执行yj′∈Y′以使W由于篡改而失效。
2.4.3.由分集获得的联锁OE、IA及RPE益处。除下述保护的要求形式外,根据本发明修改以安装联锁的代码从分集而获益,不管在修改后的联锁代码本身中,还是在这样修改的代码的附近的代码中,这通过使内部性态表现出很少重复或者通过使SBE的实例发生改变从而不同实例需要分别攻击而使攻击者的工作艰难得多。
在下述情况下出现分集:
(1)联锁中或者联锁附近的多个内部计算在其执行中发生变化,在根据本发明的修改前的原始SBE中,相应计算不是这样的(动态分集);或者
(2)在SBE的实例中,联锁中或者联锁附近的代码和数据发生变化,在根据本发明的修改前的原始SBE的实例中,相应代码片段是相同的(静态分集)。
2.4.4.联锁RPE必须是必要的。在上文中注意到,经修改的y′jBB计算经修改的函数g′j(c,e)。要求e在对g′的求值中为必要的。即,要求为了具有高可能性,对值e的任何改变将导致g′j计算出不同的结果。如果情况不是这样,则将通过输出扩展产生的额外信息e的值修改成不同的信息e′的篡改会使通过g′j产生的结果很好地保留不变。
必须确保避免了对输出扩展值的这种不敏感性,使得y′j计算g′j对e高度敏感,并且相对于计算gj(yj的计算)的正常输出,无论何时发生影响由g′j输入的额外数据的篡改,g′j都极有可能失效。
2.4.5.联锁OE必须是完整(integral)。可以通过使f′计算与f相同的结果但具有作为变元添加的常量k∈E,来平常地将实现
的例程输出扩展成实现函数
的例程,其中该变元可以通过例程的本体简单地忽略。这对于联锁是不适当的。即使常量k实际上由例程的本体使用,这是常量输入的事实构成了弱点:运行时间常量值很容易被攻击者观察到,攻击者对这种常量的知识提供了容易攻击的点。
该常量因为它是不变的而容易被发现,并且在任意x″代码中包括这种常量的产生也是价值不高的。我们希望联锁是难以被移除的,所以这种价值不高的输出扩展对于联锁来说也是严重地不当。
当有了支配BB y的BB x,这里x计算f而y计算g,如果通过添加不受输入影响的另一常量输出将f扩展为f′(即,如果将x的代码修改成产生除其普通输出之外还有某常量值的x′),则不管怎样,只要x″输出与原始值相同的常量,攻击者可以任意地将x′修改为任何任意的BB x″。
如果通过使f′计算出与f相同的结果但是某结果来自MF实现g(a)→e(这里a∈A并且e∈E,g利用a中非常有限的部分信息,诸如状态a中取决于单个变量的值)将
的实现输出扩展成计算
的例程也会出现类似的问题。这种对于状态a∈A的非常有限的依赖性提供了攻击者赖以将攻击集中于计算中非常狭窄的部分上的手段,并且通过电子欺骗输入中会影响E中结果的非常小的部分,攻击者可以移除本来由联锁提供的保护。
因此,只要根据输入对额外输出的计算是显而易见的,对于常量输出扩展的上述同样问题类似地应用于非常量输出扩展。攻击者会发现任何显而易见之处并绕过,而这恰恰正是我们要避免的。
因此,必须选择这样的输出扩展,即,对于通过替代了x的修改后的BB x′计算出的f的输出扩展f′的计算是完整的计算产生该额外输出值。额外值的产生在产生f的原始输出的f′的计算内嵌入得越深,通过该额外值的产生所修改的子计算越多,该额外输出的产生变得对于f′的计算更加完整,并且对于攻击者来说越难以移除x′和y′之间的联锁。
同样的考虑可以应用于这种情况,即,由多个BB X的集合替代x,而由多个BB Y的集合替代y,这里X支配Y。输出扩展对于X中经修改的BB的计算必须是完整的:对于X中的计算它们是越深且宽地完整的,则越好。
2.4.6.联锁OE和RPE必须是模糊的。即使RPE是必要的(见§2.4.4)并且输出扩展是完整的(见§2.4.5),除非输出扩展和RPE还是模糊的,联锁还是比我们所期望的更容易受到攻击的影响。
可以通过影响代码的各方面的各种技术来使软件变得模糊,例如参见[2、3、4、5、7、9、17、18、19、20、27]。这些技术中的某些技术的使用也可以用于使输出扩展的额外输出的计算对于原始计算是完整的,例如参见[2、3、4、5、19]。
在创建输出扩展和RPE以用于创建联锁中采用如上所述技术是本发明的优选实施方式的一部分:具体地说,另外还能够用于使得产生额外值的输出扩展计算对于产生原始输出的计算来说是完整的那些技术。
2.4.7.联锁OE和RPE必须是依赖上下文的。当利用完整的(§2.4.5)、模糊的(§2.4.6)输出扩展和必要的(§2.4.4)、模糊的(§2.4.6)RPE创建联锁时,应当避免其他可能的攻击点。
如果因为在这种输出扩展和RPE中的代码中和原始代码中采用了不同形式的计算或者不寻常的计算模式,这种输出扩展和RPE中的代码明显不同于包围它的原始代码,则这种代码由于容易被攻击者发现而被高效地标记出,有些象喷气式战斗机的水汽尾迹宣扬飞机出现过那样---完全没有什么值得做的事情可做。
因此,重要是的选择完整化和模糊化计算的方法,以及使计算成为必要的方法,这些方法是依赖上下文的:即,必须选择这些方法来使得类似于如果没有添加联锁时本来会在该代码位置的上下文中发生的计算。
假设希望在一群白鸭中隐藏一只紫鸭。使得紫鸭类似于构成了这一群鸭中的其他鸭的白鸭的三种方法是:(1)将紫鸭染成白色;(2)将白鸭染成紫色;或者(3)将所有鸭子染成绿色。
类似地,当使得引入以创建联锁的输出扩展和RPE模糊化、完整化或者必要化时,可以以三种方式使所得到的代码几乎没有什么不同:(1)通过选择能够产生看起来非常象周围代码的代码模式的修改;(2)通过修改其他代码,使得类似于注入了输出扩展或RPE代码(例如,如果利用类似的技术也使周围代码模糊化,然后经模糊化的输出扩展和RPE将不会突出出来);或者(3)通过对要注入输出扩展或RPE代码的原始上下文中的代码以及被注入的输出扩展或RPE代码都进行修改,以便具有相同代码模式。即,可以注入类似于被注入的上下文中代码的代码,或者可以修改注入上下文中的代码以类似于该注入,或者可以将上下文和注入两者修改成不是该上下文或者该注入所固有的某种模式。
必须使用上述三种技术中的任何一种或者它们的混合来隐藏联锁输出扩展和RPE。这种通过使这种输出扩展和RPE依赖上下文来隐藏是本发明的优选实施方式的一部分。优选的实施方式利用方法(3),即,优选的是利用下面描述的方法通过使在现场的原始代码和用于OE、聚合、或RPE的任何被注入代码彼此类似而使它们彼此看起来相似。
2.4.8.联锁IA必须是模糊的并且依赖上下文的。间插聚合
不应当危及联锁的安全性。这可以通过两种方式实现。
·可以定义J=K及Ragg=[R,idJ],使得用于Ragg的代码与用于R的代码等同(因为由输出扩展产生的额外信息完全未被修改地保留下来)。在这种情况下,编码输出扩展(OE)F′产生被Ragg的编码R′忽略并且随后被经编码的RPE G′使用而未被修改的额外信息。
这通常是足够的,并且对于R′不会引入额外开销。
·或者,可以针对非平凡的
定义R
agg=[R,S],这里不需要J=K。在这种情况下,一旦R
agg被编码为R′,则S的额外功能性必须以模糊的(即,难以进行反向工程)并且依赖上下文的(即,类似其周围代码)方式引入。
这引入了用于S的添加的功能性及其编码的额外开销,但增加了攻击者对联锁进行反向工程和使联锁被停用的难度。
2.5.BA代数和MBA恒等式。模糊化和防篡改软件的生成需要利用代数恒等式,如在全部[2、4、5、7、8、9、17、18、19、20、23、24、27]中所不同程度地看出。
然而,联锁要求的不寻常的迫切要求,即,对必要的RPE(§2.4.4)、完整的OE(§2.4.5)、模糊的OE、IA以及RPE(§2.4.6和§2.4.8)以及依赖上下文的OE、IA和RPE(§2.4.7和§2.4.8)的需求,要求比简单地在具体代数结构上搜索恒等式并收集这种恒等式列表更为强有力的方法。将会需要非常大量的这种复杂性的恒等式,远远超出通过使用上述文献中能找到的任何或者全部恒等式所能够提供的,然而,这些恒等式可能在这些文献中指出的使用上下文中是有用的。
然后,用于生成有效联锁的第一要求是恒等式生成处理应该是自动的,并且能够产生恒等式的有效的无限制的供应。
第二要求如下。由于联锁目的是将代码的非常具体的部分结合在一起,而不需要修改所涉及程序的大部分,因此必要的是使用恒等式必须生成难以分析的代码。组合了两种极其不同的代数结构的MBA表达式在这点上是理想的,因为它们
(1)表述简洁,因为在实际上所有现代通用二进制数字计算机上提供的硬件指令都直接支持它们,而不需要扩展成更基本的表达式或者调用例程库,并且
(2)难以分析,难以利用诸如MathematicaTM、MatlabTM或者MapleTM的符号数学工具难以进行分析,原因在于两个完全不同的域的结合(以机器字模数(通常是232或264)为模的整数计算机算术,以及对布尔向量(通常是32位或64位长)进行的逐位布尔代数运算)。
部分地,这种表达式难以分析的原因在于以两种代数结构中的一种结构表达的简单表达式变成了以这两种代数结构中的另一种结构表达的复杂表达式。从文献[20]的第4页上的表可以看出对于
上的简单运算的Z/(2
n)编码,表达式的形式变得极为复杂。从
的基本布尔运算方面考虑用于Z/(2
n)的式“·”(乘法)运算可以看出在Z/(2
n)中的基本内容在
中就变得非常复杂,并且不能通过代替地利用
来进一步简化。上述符号分析包括能够非常良好地处理单个域的普通情形,但不足以BA[n]上对MBA表达式进行解模糊化(deobfuscate)(即,将利用MBA表达式恒等式模糊的表达式简化成其原始的未模糊的形式)。
下面来讲解获取MBA恒等式的有效地无限制供应的方法。除这种恒等式的许多其他好处之外,当在SBE的生成实例中随机地改变这种恒等式中的选择时,它们还提供了用于静态分集(见§2.4.3)的强大来源。
2.5.1.将逐位表达式转换成线性MBA。假设有一个逐位表达式,
上的表达式E,利用了t个变量x
0,x
1,...,x
t-1。(对于表C中示出的真值表,t=3并且变量x
0,x
1,x
2就是变量x、y、z。)因此针对向量内任何位位置的真值表是针对同一表达式但使x
0,...,x
t-1为长度为1的向量的真值表,因为在逐位运算中,各位是独立的:同一真值表独立地应用于各位位置,因此仅需要单个位变量的真值表。真值表在其合取栏有2
t个不同项,在其二进制栏中有2
t个不同项,而在相应结果栏中具有2
t个相应的结果位(例如参见表C)。可以使结果位这一栏等同于2
t×1矩阵(具有2
t行1列的矩阵,即长度为2
t的列向量)。
现在,提供一种基于计算机算术的特性(即,基于BA[n]的属性,n为计算机字长)的相当奇妙的方法,用于将逐位表达式E的替代表述生成为BA[n]上的变量x0,x1,...,xt-1的MBA表达式。
(1)通过表示E的真值表的结果栏的内容的2t项列向量P(即,2t×1矩阵),以及还通过列向量 来汇总E,这里S因为含有符号表达式s0,s1,...,s2-1 t而代表符号,并且列向量S恰好为E的真值表中合取列的内容。
(2)获取具有从B={0,1}中选择的项的在域Z/(2)上可逆的任意2t×2t矩阵A。(例如,随机生成0-1矩阵,直到获得可逆矩阵。)
(3)如果存在A的任意列C,其中,C=P,向列C添加随机选择的A的其他列的线性组合(至少有一个非零系数)以获取其中列C≠P的新的可逆矩阵A。现在有了任何列都不等于P的可逆矩阵A。
(4)由于A在Z/(2)上是可逆的,因此A在Z/(2n)上是可逆的(如前在子标题为乘法逆元素和逆矩阵的存在与否的§2.3.2节中所述,具有增大的元素的“字长度”)。因此,矩阵方程AV=P在Z/(2n)上具有唯一解,该解可以利用高斯消元法等求得。例如,在AV=P中求解V,获得在Z/(2n)上2t个常量的列向量U,这里解为V=U,并且,
(5)然后,在BA[n]上,有 从而可以用右边的MBA表达式的和替代左边的逐位表达式E。因此,对于在字长度为n的机器上计算E的逐位指令的任何序列,可以替代为计算 的逐位及运算指令的混合序列。
(6)可选地,可以进行很多如下所述的附加推导。
根据前述第(5)段中的等式,可以通过诸如改变项的符号并将其移到等式另一侧的普通代数方法或者本领域中公知的任何其他这种方法推导出很多其他恒等式。还注意到,如果对于任何这种求和,推导出在BA[n]上的 然后如果针对变量的相同或者不同集合可以得到一系列这种求和,则因为该和等于零,因此任何数量的这些独立推导出的和的和也等于零。
这还导致这样的结论,即,将所有系数(E的系数为1,而其余系数为ui的系数)乘以常量得到另一个为零的和,由此可以容易地推导出其他有效恒等式。
例如,设E=x∨y,因此t=2。E的真值表为P=[0111]T,即仅在x=0且y=0时x∨y=0。取字长为n=32(这很大程度上被算法忽略了:机器字长在这里几乎不起作用)。
A可以是Z/(2)上任何列都不等于P的任意可逆矩阵,为使示例简单,选择
即,Z/(2)上的4×4单位矩阵。取A的元素为Z/(232)上的32位二进制数,方程AV=P在Z/(232)上有唯一解U,并且因为A是单位矩阵,该解正好为U=[0111]T,即在这个非常简单的情况下,U=P。
因此,对于计算x∨y的指令序列(通常是单个指令),可以自由替代为计算
的指令序列。
2.5.2.根据线性相关真值表推导MBA恒等式。在上述§2.5.1中,对于t个变量的逐位表达式E,使用了长度为2t的相应真值表位向量P。
现在假设对于变量的给定集合X={x0,x1,...,xt-1},有一系列逐位表达式e1,...,ek,全部应用t个变量的相同集合X,使得ei具有真值表0-1向量Pi,i=1,...,k,并且还假设{P1,...,Pk}是对于某k∈N为Z/(2n)上的向量的线性相关集合,即在Z/(2n)上存在系数a1,...,ak,使得在Z/(2n)上不是所有系数都为零并且
然后,在BA[n]上还有 根据该等式,可以通过诸如改变项的符号并将该项移到等式另一侧的普通代数方法或者本领域中公知的任何其他这种方法推导出很多其他恒等式。还注意到,如果对于任何这种求和推导出BA[n]上的 然后如果针对变量的相同或者不同集合推导一系列这种求和,则因为该和等于零,因此任何数量的这些独立推导出的和的和也等于零。
这还能得到这样的结论,即,将所有ai乘以常量得到另一个为零的和,即,对于BA[n]中的常量c,如果 还可以有 因此通过将所有系数乘以标量,还可以进一步扩展上述恒等式的推导。
作为示例,考虑表达式e
1=x,e
2=y,e
3=x∨y,
这里
表示各位位置为1的常量(常量表达式,其可以在C、C++或Java
TM中表达为-1或~0)。其相应真值表分别为P
1=[0011]
T,P
2=[0101]
T,P
3=[0111]
T,P
4=[1110]
T和P
5=[1111]
T,k=5为表达式的数量,并且在这些表达式中存在t=2个变量,使得真值表向量长度为2
t=4。
如果选择系数(a1,...,a5)=(1,1,-1,1,-1),可以得到
从而P1,...,P5是线性相关的。
因此,在BA[n]上推导出
即,
因为在带符号的2的补码解释下,等于-1。利用平凡代数操作,例如可以容易推导出
从而可以使用常量1自由替代计算上述左侧表达式的代码序列。或者,可以将任何整数值乘以上述左侧表达式而不改变它,无论x和y的值是什么。
2.5.3.BA[n]2的补码和无符号比较属性。对于生成有效联锁至关重要的是:应用于与带符号量和无符号量有关的2的补码运算和比较的一些属性,其中该带符号量和无符合量可以表示为n位字的计算机算术的代数结构BA[n]中的Bn的元素。将其列出如下。
(1) (从而 )。
(2)1x=0 iff(-(x∨(-x))-1)<0(利用带符号的比较)。这将对所有位的测试转换为仅需要在2的补码计算中高阶位的测试。
因为,在BA[n]中仅存在一个零,无论认为其元素是带符号的还是无符号的,无论是否将x本身解释为带符号的,上述公式都适用。(一般可以强制进行带符号的计算,例如,在C或C++中,可以将无符号的量x变成带符号的形式。在机器代码层面上,操作数没有类型,并且可以通过选择所使用的指令强制进行带符号的计算。)
一旦将计算结果r的单个位中的布尔结果孤立,可以容易地以其他方式操作它,例如,
r>>(n-1),
这里如在C或C++中,“>>”是右移算子,如果移位是带符号的,则将布尔结果复制到字的所有n位中,而如果移位是无符号的,则将其转换成代表“真(true)”的值1或者代表“假(false)”的值0。
因为x≠0 iff(x=0)为假,上述属性可以用来将BA[n]上的=和≠比较转换成其布尔结果的任何期望表示。
通常,选择表示true=00...01和false=00...00(这里布尔值为低阶位,而其他位为零),或者选择表示true=11...11和false=00...00(这里布尔值表示在全部位中)。
将前者称为1位(one-bit)布尔表示,而后者称为全位(all-bit)布尔表示。
(3)2x=y(带符号或无符号)iff x-y=0-可以利用上述(2)的恒等式来测试差异。
当x=y,则x∨y=x∧y=x=y,x-y=x⊕y=0,
(带符号或无符号)=-1(带符号),
(带符号或无符号),
(带符号或无符号),类似地,对于任意k,
(带符号或无符号)。
(可以通过简单的代数操作或者通过与下述恒等式进行组合很容易推导出许多其他这种包含x和y的恒等式,所有这些对于这种推导的领域的技术人员来说都是明显的,所述恒等式为§2.5.3中公开或引用的恒等式、或者通过在§2.5.1和§2.5.2中给出的方法得到的恒等式、或者在[2、4、5、20]中公开的恒等式、或者在§2.7.7中给出的[20]的扩展中得到的恒等式、或者下面在§2.5.4中描述的恒等式。)
(4)3根据Hacker′s Delight[28]:x<y(带符号),
(带符号)。如上所述,这孤立了右侧计算
(称其为r)的结果的高阶位中的布尔值1(true)或0(false)的结果,由此可以将其转换成任何期望的布尔表示。此外,
-y>x(带符号)iff x<y(带符号),
-x≥y(带符号)iff x<y(带符号)为假,并且
-y≤x(带符号)iff x≥y(带符号),
因此,上述公式使得能够将BA[n]上带符号的不等式运算的全部范围转换成其布尔结果的任何期望表示,如上述(2)中所述。
(5)4根据Hacker′s Delight[28]:x<y(带符号)
(带符号)。如上所述,这孤立了右侧计算
(称其为r)的结果的高阶位中的布尔值1(true)或0(false)的结果,由此可以将其转换成任何期望的布尔表示。此外,
-y>x(无符号)iff x<y(无符号),
-x≥y(无符号)iff x<y(无符号)为假,并且
-y≤x(无符号)iff x≥y(无符号),
因此,上述公式使得能够将BA[n]上无符号的不等式运算的全部范围转换成其布尔结果的任何期望表示,如上述(2)中所述。
2.5.4.组合布尔条件。如上§2.5.3中所述,可以获得BA[n]内布尔形式的独立比较结果,用n个“0”位的序列表示假(false),而用n-1个0位后面接着一个“1”位的序列表示真(true)或者用n个“1”位的序列(全位布尔表示)表示真(true)。
可以通过带符号的运算否定将一位(one-bit)表示转换成全位(all-bits)表示(因为0和-1的2的补码表示分别为00...00和11...11),并且可以通过将值无符号地右移n-1个位置将全位表示转换成一位表示,这里n为字长。
表E-利用布尔表示进行计算
可以组合这些布尔值以在同一表示中产生新的布尔值,如上表E中所示。注意,除一种特殊情形外,逻辑运算的BA[n]表示是对应的逐位运算。唯一的例外是:在一位布尔表示中,我们按00...01⊕x计算
其仅转换低阶位。
2.5.5.求Z/(2n)和GF(2n)中的乘法逆元素。常常需要求出Z/(2n)或GF(2n)中的元素的乘法逆元素以便根据[17、18、20]建立矩阵、线性恒等式、编码和模糊等。
这对于Z/(2n)中的数可以利用小型高效算法(扩展欧几里得算法[10、22])以O((log n)2)个步骤来高效地实现。
将通过该算法计算出的函数表示为E,对于a,b∈N且a≥b,有E(a,b)=(x,y,d),这里d为a和b的最大公约数,并且在普通整数运算中(而不是在某有限环或者其他有限代数结构上)有ax+by=d。
因此,为了求出Z/(2n)中某奇数b的乘法逆元素,计算E(2n,b)=(x,b-1,1)。忽略x。b-1为在Z/(2n)中b的期望乘法逆元素。
当然,一旦得出b-1,就知道b-k,k>1,因为b-k=(b-1)k。
类似地,对于GF(2n)的元素,可以利用扩展欧几里得算法[11]的多项式形式可以有效地求出GF(2n)的元素的乘法逆元素,其计算是在GF(2)上而不是GF(2n)上的多项式的无限环中执行,其求出逆元素需要O(n2)步。将通过该算法计算出的函数表示为E′,对于元素a,b∈GF(2n),当a的次数大于b的次数时,E′(a,b)=(x,y,d),这里,d为a和b的最大公约数,并且在GF(2n)上ax+by=d,其中a,b,x,y,d为GF(2n)中的多项式。
然后,设I为在GF(2n)的所选表示中使用的GF(2)上的不可约多项式,如果b为多项式1,则其逆为其本身。否则,b为一次或更高次多项式,并且为了求出其逆,计算E′(I,b)=(x,b-1,1)。丢弃x。b-1是期望乘法逆元素。
当然,一旦求得b-1,即可知b-k,k>1,因为b-k=(b-1)k,这里在GF(2n)中执行求幂。
2.5.6.MBA的普遍性。利用整数加、减、乘和求幂由整数值变量建立的任何表达式可以转换成MBA表达式。
这可以立即从任何变量能够表示为加性对等物的事实得到,即任何值v可以表示为对于某种选择的v1,...,vk的值的和v1+...+vk。实际上,如果固定列v1,...,vk中除vi外的所有元素,仍然可以通过适当选择v1,...,vk中未固定的vi能够产生期望的和v,这里k≥2。
因此,可以很容易用MBA表达式代替上述固定值v1,...,vi-1,vi+1,...,vk中的任何一个或者全部,将变量转换成其加性对等物v1,...,vk的MBA表达式。
然后,对于n≥1个变量a,b,...,v,...,z的任意表达式(是根据这些变量通过利用加、减、乘和求幂建立的),通过用变量的加性分割替代表达式中的原始变量,可以获得值与原始表达式相同的MBA表达式。
除上述方法外,当然还可以有机会通过利用根据在§2.5.1和§2.5.2中教导的方法生成的MBA恒等式的无限供应来替代子表达式。这些方法的组合提供了将变量的任意代数表达式转换成MBA表达式的强有力的方法。
2.6.隐藏静态和动态常量值。常量值可以是静态常量(在编译使用了该常量的软件时具有固定值的常量)或动态(即,相对或者临时)常量(当编译使用了该常量的软件时不能获得该常量,但该常量在该常量希望支持的计算值范围内首次计算出该常量之后不再变化,从而它是“相对恒定的”、“暂时恒定的”或者“在动态发生的临时时间间隔上是恒定的”)。动态/相对/临时常量的一个示例是随机选择的加密会话密钥,其用于有限时段上特定的一组通信。这种会话密钥的使用通常与公共密钥加密学有关,因为诸如RSA公共密钥密码系统或者椭圆曲线公共密钥密码系统的公共密钥密码系统加密和解密时比诸如AES的对称密钥密码慢。因此,RSA用于建立会话密钥,然后会话密钥用于处理该会话期间发生的其余信息传递。
首先考虑以最一般的形式隐藏静态和动态常量的方法,然后将该形式与这里公开的参考文献及其扩展所包括的模糊和防篡改方法相关联,并与这里公开的模糊和防篡改其他方法相关联。最后,考虑这样一种方法:隐藏常量中使用的常量本身是动态常量,从而同一程序的不同执行,或者利用了瞬间隐藏常量的程序的同一部分的连续执行在彼此之间动态地改变。
一般方法。假设系统方程(不一定是线性的)具有以下形式
y1=f1(x1,x2,...,xm)
y2=f2(x1,x2,...,xm)
yn=fn(x1,x2,...,xm),
或者等效地,具有x=(x1,...,xm),y=(y1,...,yn)并且f=<f1,...,fn>,则有y=f(x),这里,f为BA[n]上(通常为BA[32]或BA[64]上)的n×m向量函数。假设f在普通数字计算机上可有效地计算的。
如果存在特定索引i,1≤i≤m,函数g,xi=g(y)=g(y1,...,yn),这里g也是在普通数字计算机上可有效地计算的,则可以将f用作隐藏静态或动态常量c=xi的手段。
如果存在特定索引i,1≤i≤m,函数g,xi=g(y)=g(y1,...,yn),这里g也是在普通数字计算机上可有效地计算的,则可以将f用作隐藏静态或动态常量c=xi的手段。
我们的方法是要选择常量----可以动态的/相对的/临时的----这里c=xi是要隐藏的常量。可行的是,在f中的计算上执行常量折迭-PE的一种形式(见§2.3.3)-其使得特异常量c=xi以及模糊化常x1,...,xi-1,xi+1,...,xm被计算和新常量的组合所替代。当需要c时,不是读取c,而是用计算g(y)=g(y1,...,yn)来代替读取c。
当然,当隐藏动态常量时,很少发生常量折迭,因为在正隐藏该常量时许多子表达式具有未知的值,因此向量x、动态常量y、函数群集f和函数g之间的关系在运行之前部分是符号,这意味着在运行的程序中安装的公式涉及到采用由变量而不是静态常量提供给计算的实际动态的值。
保护在隐藏常量的入口附近的代码。为实现该处理,需要通过[2、4、5、9、17、18、19、20]的方法,或者这里提供的这些方法的扩展(见§2.7和§2.8),或者通过使用利用了§2.5.1或§2.5.2的方法得到的恒等式,或者§2.5.3中公开或者引的用的恒等式,或者§2.5.4中公开的恒等式,或者通过应用[20]的扩展有在§2.7.7中描述的编码的新非线性形式的方法,或者通过上述方法的任何组合,对使用该常量的代码及在该代码的直接附近区域的代码进行编码。
通过在§2.5.1的介绍的结尾处教导的所选恒等式当中的SBE实例之中的随机变量,可以将静态分集添加到这种保护中。
一个简单示例。如果通过基于矩阵的仿射函数y=Mx+d来定义m=n和y=f(x),这里M为Z/(2k)上的n×n矩阵,y为列向量,x为列向量,而d为常量位移(displacement)列向量,并且如果M是可逆的(即,具有奇行列式),则对于x1,...,xn的任意选择,可以确定在1≤i≤n范围内的任何i的公式,通过该公式可以根据y确定x。因此,通过消除任何不需要的计算,可以通过由x=M-1y-M-1d定义的逆函数的更大计算推导出g来推导出函数c=xi=g(y1,...,yn),其仅包括求出c=xi所需要的那些计算,省略了仅仅是找出x1,...,xi-1,xi+1,...,xn所需要的任何计算,由x=M-1y-M-1d定义的逆函数本身是与原始函数形式相同的基于矩阵的仿射函数,但具有不同矩阵M-1和不同常量位移列向量-M-1d。
可以利用[2、4、5、20]中公开的恒等式,或者§2.5.3中公开或者引用的恒等式,或者§2.5.4中公开的恒等式,或者使用§2.5.1或§2.5.2的方法得到的恒等式,或者通过利用由[20]中的映射提供的逆元素得到的恒等式或者通过§2.7.7中的附加非线性映射得到的它们的扩展,或者通过上述的任何组合,来得到许多其他类型的n×m向量函数f和常量提取函数g,这对于熟悉代数操作的人员来说是显然的。仅需要考虑直接推导,学习了求模整数环的大学一二年级学生很容易进行该推导,因此很容易按照计算机程序执行的操作实现自动化,这提供了大量各种各样的选择,对于提供足够的模糊来说绰绰有余。注意:f=<f1,...,fn>的数学域(mathematical domain)及g的数学域与要由g提取的常量c的预期数学域无关。作为一个示例,上面给出的矩阵方法可以利用基于整数的无限环的矩阵,然而返回被解释为表示GF(2)上的多项式的位串的值,常量的各位表示多项式的系数。注意:任何长度的常量值可以通过以片段生成该常量来进行调节,其中各片段具有便于待保护的软件目标平台使用的长度。例如,可以通过分离地、每次一个矩阵元素地利用上述方法来生成矩阵常量。
复杂性越大,安全性越高。在上面的简单示例中,函数f和g是在Z/(2k)上仿射的。注意到,可以很容易根据f-1求出(通过忽略输出)由f给定的系统方程的解g,这对于精通大代数的人来说是明显的。
因此,可以采用根据下面的方案:利用宽输入深度非线性函数中公开的方法构造的深度非线性函数f,然后构造根据下面的所构造的深度非线性函数的求逆中公开的方法推导出的f和f-1;然后给定f-1,然后通过忽略f-1的某些输出求得g。
当使用该方法时,希望可以利用f,进而利用具有经编码的输入和输出元素的f-1和g。如果是这样,建议利用下面的替换盒的替代中提议的方法对它们进行编码。
添加动态随机性。一般方法中的常量x=(x1,...,xm)可以是动态常量。这意味着用于在给定y=(y1,...,yn)的情况下找回c=xi的解函数g将利用符号、通解,该通解可以通过用x1,...,xi-1,xi+1,...,xn的具体值代替保持这些动态常量的变量来应用于具体的、特定的情况。结果,常量折迭可以实现较少的优化。然而,该方法仍然是有效的。
为了获取动态常量x1,...,xi-1,xi+1,...,xn,采用§2.10.7中公开的方法,由此添加动态分集(见§2.4.3)。
2.7.通过引用结合进来的和这里扩展的方法和系统。在此通过引用将下述专利中的方法和系统全部并入本申请中:美国专利6,594,761[2]、美国专利6,779,114[3]、美国专利6,842,862[4]、美国专利公开No.2004/0236955 A1(申请号10/478,678)[5]、美国专利公开No.2003/0163718 A1(申请号10/257,333)[16]、美国专利公开No.2004/0139340 A1(申请号10/433,966)[17]和2006/0140401A1(申请号11/020,313)[18]和美国专利公开No.2005/0166191A1(申请号11/039,817)[20][全部都转让给了与本申请相同的受让人,Cloakware公司,Ottawa Canada(加拿大渥太华),起于2006年7月18日]。
为了用于联锁中,推荐对上述方法和系统进行加强,因为在联锁中集中、有目的地使用这些方法要求保护力度最大化。因此,公开了下面的用于加强上述方法和系统的方法。
其中,利用上述形式的保护以及下面教导的扩展来建立联锁元件中所要求的模糊性(obscurity)和上下文性(contextuality)的属性,如§2.9.2中所教导的。
[2、3、4、5、16、17、18、20]的方法和系统都取决于所提供的熵(播种伪随机值流的有效随机信息输入,在应用这些方法和系统中基于该伪随机值流作出进行编码和保护判定)。因此,它们都提供高次的静态分集:这些方法和系统的每次重新使用通常产生不同的结果,由此使得攻击者的工作更加困难,因为对“利用上述方法和系统将给定原始未保护SBE修改成了受保护的SBE的实例”的攻击必须基于预生成的实例而变化。
此外,当以下各节教导的扩展采用可通过§2.5中教导的手段发现的MBA恒等式时,可以通过SBE实例中使用的恒等式中的变型向其保护添加静态分集,如§2.5的介绍结尾处所述。
2.7.1.向6,594,761和6,842,862添加新的编码。美国专利6,594,761[2]设计了许多不同类型的数据编码,包括在整数环或者被逼近在浮点数上的一维(每次一个标量变量)和多维(每次多于一个变量)线性及多项式编码、基于根据中国剩余定理的整数求模分解的余数编码、位分解(bit-exploded)编码以及查找表编码。美国分案专利6,842,862[4]和美国专利申请10/478,678[5]添加至这些编码,其中一个变量的编码依赖于另一个变量的编码,或者其中多个变量被编码成各变量的表示随其他变量的表示而变化,并且将许多这种编码组织成方程的相关系统,以协调诸多不同数据段的编码,由此产生在篡改攻击下的主动易损性。通常,这些专利和申请的组合提供了这样的系统,通过该系统,可以进行程序中的许多计算,参照图1,将d,d-1,c,c-1,R,R′全部限制为函数,用经编码的计算替代程序区域上的明文计算,使得
·各数据经过编码,不管是存储的数据、作为输入消耗的数据,还是作为输出产生的数据,以及
·还对计算进行编码,从经编码的输入计算经编码的输出,而不在任何点产生明文值,除仅在区域的边界外,进入该边界的数据以明文形式被消耗,并产生明文结果。即,在区域内除其周边外的任何地方,计算对应于图1的底线,其中对攻击者来说,仅有经编码的数据和值是可见的。此外,由于[4]中公开的编码的协调系统,这种计算是相互依赖的并且在篡改下是主动易损的,因此任何激发攻击者篡改这样保护的软件的目标导向的企图几乎都不可能实现。
和[4]的余数编码、位分解编码、位内爆(bit-imploded)编码、基于定制的编码及位制表(bit-tabulated)编码需要极大的开销。通过添加基于有限环Z/(2n)的编码,这里n是以位为单位的目标计算机字长度,可以通过采用[20]的线性环编码及其利用二次、三次及四次多项式的逆而扩展到二次、三次及四次多项式的多项式扩展(如这里在§2.7.7中所公开的),来减小开销并增强安全性。
此外,还可以通过对利用了根据下述恒等式的替换的编码进行预修改和/或后修改来加强专利[2]和[4]的现有编码,由此使得由于这些编码同时在计算内使用多个极为不同的数学域的原因而不能利用诸如MathematicaTM、MatlabTM或MapleTM的工具分析这些编码,其中,所述恒等式可以是在§2.5.3这里所公开或者引用的恒等式、或§2.5.4中公开的恒等式、或通过利用§2.5.1和§2.5.2中这里给出的方法而找到的恒等式。
2.7.2.向10/257,333添加新的单元和地址编码。美国专利申请10/257,333[16](其描述了用于保护海量数据(阵列、I/O缓冲及消息缓冲、大小可调的数据结构等)的方法和系统)的方法和系统要求将使用的存储器分成多个单元,这些单元是通过变换后的单元号码来寻址的而不是通过根据[16]的在编码之前已经用于访问数据的索引或偏移量(offset)来寻址的,并且要求从这些变换后的形式的单元取回数据并向这些变换后的形式的单元存储数据。
结果,大量地利用了各种变换。[16]中提供的变换种类中的一种是这里描述的逐点线性分割双射(PLPB)。注意到[20]的编码是可高速、紧地实现的PLPB的一种特殊情况。([20]公开了许多附加的创造性内容,例如用于使用这种编码而不需要使用[16]中为PLPB构思的辅助表的方法。)
为使[16]的方法所提供的保护最大化,因此推荐通过使用[20]的编码的扩张(如这里有§2.7.7中所扩展的),用于作为对[16]中构思的某些或全部单元和地址的编码。还推荐进一步通过应用§2.5.3中公开或引用的恒等式、§2.5.4中公开的恒等式、或者通过§2.5.1、§2.5.2和§2.5.4中公开的方式找到的恒等式来进一步保护由[16]构思的从各单元取回数据、向各单元存储数据及对数据重新编码的某些或者全部,以使得自动代数分析工具不可能有效地侵入这种编码。
2.7.3.保护6,779,114中的分派常量及分派表。美国专利6,779,114[3]中公开了这样的方法和系统,其中,程序的控制流可以重构成这样的形式:通过具有带索引的控制的多路分支实现控制的局部传递(如图4(b)的switch语句)。通过数据值执行带索引的控制,并且存储全部必要数据值所需要的信息都存储在主表中,或者分成多个表,如[3]中第32栏从15行开始的部分中所公开的。
如果对该表或者这些表的内容以及用于对其进行寻址的索引都进行编码,则该表或这些表将是极为安全的。为此,推荐使用[16]的海量数据方法,使各单元为表元素,利用上面在本文§2.7.2中公开的向[16]中添加所提议的扩展以使这种编码极难于通过利用代数分析工具进行分析。或者,这些表可以采用带有在本文§2.8.1中公开的改进的[9]的阵列保护,或者,如果要保护的程序是富循环的(明示的或者隐含的),则采用[27]的阵列保护。
此外,根据[3]的方法和系统所保护的软件代码可以在分派中大量使用常量。由于这种常量在编码之后出现,因此可以通过本文§2.6中公开的方法隐藏这种常量,进一步保护软件免遭攻击者进行的解模糊或者有效篡改。
最后,由于原始程序中的条件分支的原因,通过分派表对分支中使用的分派常量进行的判定通常是条件性的。这些条件应当利用已经被执行了多种替换的代码进行计算,所述多种替换为§2.5.3中公开或者引用的各种替换、或者§2.5.4中公开的各种替换、或者通过§2.5.1或§2.5.2中公开的方法得到的各种替换、或者[2、4、5、20]中公开的替换或在§2.7.7中给出的对[20]的扩展中公开的替换,并且优选地这些替换中的某些或全部替换的组合。或者,可以利用具有在本文§2.8.1中公开的改进的[9]的不透明预测法(opaque prdicate method)使这些条件变得模糊。
可以通过在应用美国专利6,779,114[3]以及上面所列改进之前执行条件依赖联锁(如§2.10.4中所公开)以保护分支来进一步加强上述技术。
实际上[25]中描述的攻击形式不可能成功地对付根据具有刚刚在上面公开的改进和附加保护的美国专利6,779,114[3]所保护的软件,因为该攻击所基于的关键假设对这样保护的软件不成立。
2.7.4.减少6,779,114中的开销。在§2.7.3中公开了用于增加通过美国专利6,779,114[3]的方法和系统提供的控制流保护的安全性的方法。
的开销或者根据§2.7.3扩展的[3]的开销可以是实质性的,因为集总(lump)(见[3]中第16栏第5项)通常包含至少两个片(见[3]中第16栏第4项),各片通常包括在多于一个的集总中,以使实现代码中功能性到位置的m到n映射(m>1且n>1)。即,待保护的代码中的各单个计算通常在已经应用了[3]的保护的修改后的代码中出现两次或更多次。
因为有许多其他手段来提供控制流保护,例如在§2.10、§2.10.5和§2.11.1中所公开的保护手段,因此可以应用这些保护手段并且无需要求代码复制的[3]中的那些保护或在§2.7.3中的扩展。这样的效果是各集总仅包含一个片,其消除了将例程组成“超大例程”(VLRs:very large routines)的要求,或者向由集总得到的代码提供多个入口点或者多个出口点来执行虚拟寄存器(VR:virtual register)切换的要求。因此与根据[3]保护的代码的普通性态相反,竞争性地执行每个片(即,执行有用的计算),其中,在给定的集总中给定片的出现的一些执行是竞争性的,而其他执行仅仅是连接性的(即,为了随机化的目的而携带着熵,但不执行原始程序的计算)。
当然,保留分派表,但这些表极小,并且是一维的而不是二维的,因为它们仅需要基于每个标签对代码进行寻址,而不是基于每个标签-角色-对,其中标签标识了分派表中的具体集总。
可以将上述开销缩减应用于待保护的代码中的小部分、中等部分或者大部分,或者应用于待保护的代码的全部。
2.7.5.向10/433,966和11/020,313添加深度非线性。美国专利申请10/433,966[17]和11/020,313[18]公开了创建密码建立块的方法,即使它们被配置在白盒(white box)攻击环境(即,即使攻击者已经完全获取了应用程序的执行时)也能抵抗密钥提取。
替换盒的替代。[17]针对任意编码利用了替换盒(SB),即查找表。注意到,这种表可以非常大,并且用于这种编码的有价值的替代是将[20]的编码中的任意选择与在§2.7.7中公开的对它们的增强一起使用,即,替代严格随机函数,使用1到4阶(包含1阶和4阶)置换多项式。对于这种函数,仅需要系数,而不需要整个表,这极大地节省了空间,并且根据上述方法很容易构成多项式及它们的逆。
问题。这些方法是有价值的,但就其本身而言,它们遭遇到一定的公开形式的攻击及其同盟。例如,已经利用[1]中的攻击侵入了[7]中描述的利用[17]的方法建立的AES-128实现。虽然该攻击成功了,但该攻击非常复杂,并且需要相当大的人力来应用于任何具体的软件实现,因此即使没有修改,[17]的方法也是相当有用的。极难使[1]的攻击能够成功地抵抗对根据[18]加强后的根据[17]的实现所进行的攻击。然而,结合联锁,寻求到强有力的保护,因此有益地是为了使诸如[1]中的攻击的那些攻击完全不可行找出进一步防护[17、18]的方法的方法。
更多的使用是在根据[17、18]的宽输入线性变换([17]中的§4.0)以及§4.1中9-10页([17]中第[0195]-[0209]段)中描述的矩阵分块方法(matrixblocking method)的实现中进行的。[17]的方法确实产生了这种线性变换矩阵的非线性编码实现。然而,这些实现只是浅层的非线性的。即,将这种矩阵转换成替换盒(查找表)的网络,替换盒(查找表)由于空间限制的原因而必需具有有限数量的元素。对用于对这种盒编索引的值以及从这种盒检索到的元素值进行的非线性编码(任意1对1函数,其本身可表示为替换盒,即查找表)同样由于空间限制的原因而限于有限范围。
因此,通过这种分块后的矩阵表示(其被实现为替换盒的网络或者用于实际上表示任意随机函数的类似装置)的输入输出编码实现所计算的任何数据变换是直到I/O编码之前线性的,即,任何这种转换都可以通过对各输入向量元素单个地进行重新编码并且对各输出向量元素单个地进行重新编码来转换成线性函数。
中的攻击方法是基于同态映射的一类攻击的一个特定实例。攻击利用了线性函数的已知属性,在这种情况下是在GF(2
8)上,因为这是AES中计算的代数基础。具体地,利用逐位⊕(异或)执行GF(2
n)中的加法,并且该函数定义了精确已知形式的拉丁方。因此,可以搜索从⊕的编码查找表版本到未编码查找表版本的同态,并且在任何函数f=Qо⊕оQ
-1(这里⊕是逐位的)的情况下可以以合理的效率求出针对特定仿射A的近似解
(即,实数Q的仿射映射A内的近似解
)。在[1]的攻击中利用到了这些事实是,并且存在能够类似地利用[17、18]中的分块后矩阵函数实现是直到I/O编码之前线性的这一事实的其它攻击。当这种攻击仅产生部分信息时,它们可以将确切信息的搜索窄化到通过穷举搜索就能够探索出其余可能性的点上。例如,利用[17、18]提供的建立块进行的加密或解密的白盒实现可能容易受到诸如[1]中那样的密钥提取攻击,或者基于同态映射的相关攻击。
方案:利用宽输入深度非线性函数。该方案是要用这样的函数替代这种矩阵函数,其为(1)宽输入的,即包含单个输入的位数量大,从而可能的输入值的集合相当大,并且为(2)深度非线性的,即不可能通过I/O编码(即,通过单个输入和单个输出单独进行重新编码)转换成线性函数的函数。
使输入宽可以使通过将所有输入上的函数制成表的强行转换不可行地消耗大量存储器,并且深度非线性防止了诸如[1]中那样的同态映射攻击。
例如,可以用输出和输出64位(8字节)值的深度非线性MDS变换替代在输入和输出32位(4字节)值的AES中的MixColumns和InvMixColumns变换,使这些中每个的强行转换是不可能的。称这些变型为MixColumns64和InvMixColumns64。(因为消息的加密是在发送方完成的,而解密是在接收方完成的,这些通常不会在相同的网络节点上出现,因此攻击者通常仅能够访问其中之一)。
例如,假设需要在GF(2n)(这里n是用于该实现的多项式(即,位串)的大小)上,或者相应地在Z/(2n)(这里n为期望元素宽度)上构造这种深度非线性向量到向量函数。设u+v=n,u和v为非零正整数。设G=GF(2n)(相应地,Z/(2n)中)中所选择的表示,Gu=GF(2u)(相应地,Z/(2u)中)中所选择的表示,而Gv=GF(2v)(相应地,Z/(2v)中)中所选择的表示。
假设需要执行深度非线性函数
P≥3并且q≥2;即,在GF(2
n)的所选择表示G上将p个向量映射到q个向量上的函数。
如果需要线性函数,可以利用G上的q×p矩阵构造一个线性函数,并且如果需要过去是非线性的但是直到I/O编码前是线性的函数,则可以利用根据[17、18]的这种矩阵的分块后的编码实现。然而,这些方法并不足以获得深度非线性。
注意到,G、Gu、Gv的元素都是位串(长度分别为n、u、v)。例如,如果n=8并且u=v=4,则G的元素为8位字节,而Gu和Gv的元素为4位的半字节s(字节的一半)。
我们引入运算extract[r,s](.)和interleave(·,·),它们是在实际任何现代计算机上可容易地实现的,这对于精通通过编译器进行代码生成的人员来说是显然的。对于位串
s=(b0,b1,...,bt),
定义
extract[r,s](S)=(br,br+1,...,bs);
即,extract[r,s]返回位r到s(包括端值)。对于位串向量
V=(S1,S2,...,Sz),
定义
extract[r,s](V)=(extract[r,s](S1),extract[r,s](S2),...,extract[r,s](Sz))
即,extract[r,s]返回包含各旧向量元素的位r到s(包括端值)的新向量。对于相同长度的位串的两个向量,如V=(S1,...,Sz)和W=(T1,...,Tz),定义
interleave(V,W)=(S1‖T1,S2‖T2,...,Sz‖Tz)
即,interleave(V,W)的各元素为V的相应元素与W的相应元素的拼接。
(1)1选择线性函数或者等同地,选择Gu上的q×p矩阵。(因为奇异方子阵能够创建对同态映射的脆弱性,因此优选地,L的矩阵表示中的大多数方子阵是非奇异的。如果L是MDS,则L的方子阵都不是奇异的,因此肯定满足该优选情况。)
(2)选择k≥2的线性函数
i=0,...,k-1,或者同等地,选择k≥2,G
v上的q×p矩阵。(因为奇异方子阵能够创建对同态映射的脆弱性,因此优选地,R
0,...,R
k-1的矩阵表示中的大多数方子阵是非奇异的。如果R
0,...,R
k-1是MDS,则任何R
i的方子阵都不是奇异的,因此肯定满足该优选情况。)
(即,选择s为“映成的”或者“满射的”)。
除s是映成的要求外,可以随机选择s。然而,即使简单的构造也足以获得s。作为示例,给出s的优选构造,如下。
如果k≤u,则选择线性函数
(或者等同地,G
u上的1×p矩阵)和函数
类似地,如果u<k≤2u,则选择线性函数
和函数
等。然后使s=s
2оs
1。在该优选实施方式中,k为2、4、8,或者2的其他次幂。
假设k=2。则s2可以返回Gu的元素的位串表示的低阶的1个位;如果k=4,则s2可以返回低阶的2个位,而一般地,如果k≤u,则s2能够返回位串以k为模的值,比如,对于优选地选择k=2m是通过提取s1输出的m个低阶位获得的。
上述优选实施方式允许我们能够使用s1的分块后的矩阵实现,从而[17、18]的方法适于它。此外,当f可逆时利用该优选的构造,通过下面公开的方法,可以直接获取f-1的实现,下面公开的方法生成了构造类似于f的构造的f-1函数。
(4)对于任何V∈Gp,设
Vu=extract[0,u-1](V)
Vv=extract[u,n-1](V),以及
f(V)=interleave(L(Vu),Rj(Vv))
其中j=s(Vu)。
(5)上述步骤(4)中定义的函数f可能是深度非线性的,也可能不是深度非线性的。然后下一步是要检查深度非线性。利用以下检测来确定深度非线性。
如果f是深度非线性的,则如果将其输入中除一个以外的全部都冻结为常量值,并忽略其输出中除一个以外的全部,则得到1×1投影f′。如果为被冻结的输入选择不同的值,则可以获得不同的f′函数。对于线性函数,或者直到I/O编码前是线性的函数,可以容易地计算出通过为被冻结的输入选择不同的值可获得的相异f′函数的个数。例如,如果p=q并且f为1对1(即,如果L,R0,...,Rk-1为1对1),则恰好存在|G|个这种函数。如果q≥p则在这种构造中f只能是1对1的。
简单地对这种f′函数(表示为G上的|G|个向量)进行计数(即,通过利用散列表以存储在p-1被冻结输入常量在所有可能性上变化时各向量的出现次数)。如果不能通过用p×q矩阵替换f来获得相异f′函数的个数,则f是深度非线性的。
可以通过注意到可以不是对f而是对f的任意1×3投影g来执行上述测试来加速该测试,这里g是通过将输入中除三个以外的全部都冻结为常量值并忽略输出中除一个以外的全部来获得的。这减小了需要针对从|G|p-1到|G|2的给定未冻结输入和给定未忽略输出进行计数的函数实例的数量,从而实际上是提高了速度。此外,如果f是深度非线性的,则这在测试期间可以很快发现:绝对第一次发现不能从矩阵获得投影函数计数,可知g是深度非线性的,因此f是深度非线性的。
如果使用了具有随机选择的三个输入和一个输出的g的加速,并且没有成功证明f的深度非线性,则f可能是直到I/O编码之前线性的。
(注意,可通过矩阵来获得投影实例计数但f仍然是深度非线性的。然而,这不可能偶然发生,并且我们可以忽略它。在任何情况下,如果上述测试表明f是深度非线性的,则它肯定是深度非线性的。即,在深度非线性的测试时,上述测试会产生错误否定,但决不会产生错误肯定。)
(6)如果步骤(5)中的测试没有表明f是深度非线性的(或者,对于紧接着该列表之后的变型,充分深度非线性),则返回到步骤(1)重新再来。
否则,获得了期望的深度非线性函数f就结束该构造。
作为上述情况的变型,希望获得是深度非线性的函数f,并且不仅如此,而且其投影也是深度非线性的。在这种情况下,在上述步骤(5)中,可以增加具有随机选择的三个输入和一个输出的相异组的函数g的数量,对此必须表明f′实例计数是不能通过矩阵获得的。对这些测试得越多,越能够确保f不仅是深度非线性的,而且在其域的所有部分上都是深度非线性的。必须权衡这种测试的成本与获得这种保证在其域的越来越多部分上是深度非线性的深度非线性函数的重要性。
实验验证。利用伪随机地生成的MDS矩阵L和R
0,R
1(k=2)来尝试用于构造深度非线性函数f的方法的该优选实施方式的1,000次伪随机试验,这里
G=GF(2
8)和G
u=G
v=GF(2
4)。利用带有伪随机地选择的相异系数的范德蒙(Vandermonde)矩阵法生成MDS矩阵。在最终的1,000函数中,有804个是深度非线性的;即,在构造方法的804个执行中,步骤(5)表明该方法在其第一次尝试时已经产生了深度非线性函数。
替代使用根据本优选实施方式的选择器函数s=s2оs1,将函数s2实现为16个1-位元素的表来执行类似的实验,该表具有从集合{0,1}伪随机地选择出的各元素。在1,000个这种函数中,有784个是深度非线性的;即,在784个构造中,步骤(5)表明构造方法的第一次尝试已经产生了深度非线性函数。
最后,将s创建为从Gu 3映射到{0,1}的伪随机地选择的元素的表来执行类似的实验。在1,000次伪随机试验中,这产生了997个深度非线性函数。因此,该方法产生了最高比例的深度非线性函数。然而,需要大小可调节的表(对于这种小型实验为512字节;而对于具有与AES的MixColumns矩阵相同的I/O维度的类似函数为2,048字节)来存储s。
然后可以看到,上面给出的用于在有限域和环上创建深度非线性函数的构造方法是非常有效的,并且具体地说,其优选实施方式是非常有效的。此外,如下可以看到的,可以直接创建所生成的深度非线性函数的逆函数。
上述构造的属性。按照上述方法构造的深度非线性函数
具有以下属性:
(1)如果L和R1,...,Rk是1对1的,则f是1对1的;
(2)如果L和R1,...,Rk是双射的(即,如果它们是1对1并且是映成的,则有p=q),则f是双射的,并且
(3)如果L和R1,...,Rk都是最大距离可分的(MDS,见下面内容),则f是MDS。
两个k向量(比如u=(u1,...,uk)和v=(v1,...,vk))之间的汉明距离为u和v不同的元素位置的数量;即,它是
Δ(u,v)=|{i∈N|i≤k并且ui≠vi}|
最大距离可分(MDS)函数
(这里,S为有限集并且|S|≥2)是这样的函数,对于任意x,y∈S
p,如果Δ(x,y)=d>0,则Δ(f(x),f(y))≥q-d+1。如果p=q,则这种MDS函数总是双射的。通过将输入中的m<p个冻结为常量值并忽略输出中除n<q(n≥1)个以外的全部获得的MDS函数
的任何投影f′(从而
)也是MDS函数。如果S是有限域或有限环并且f是通过q×p矩阵(MDS矩阵,因为其计算的向量变换是MDS)(比如,M)计算出的函数,则通过删除M中除z行之外的所有行然后删除除了z列之外的所有列(z≥1)获得的任何z×z矩阵M′都是非奇异的;即,M的各个方子阵是非奇异的。
这种MDS函数在密码学中是重要的:因为它们用来执行一种“理想的混合”。例如,AES密码[15]在其各轮中除最后一轮外利用MDS函数作为两个状态元素混合函数中的一个函数。
所构造的深度非线性函数的求逆。当采用针对某有限域或有限环G的1对1深度非线性函数
时,通常还需要f的逆,或者至少是相对逆。(就[17、18]而言,对应情况是,具有1对1线性函数
其在I/O编码之后为浅非线性的,需要其逆或相对逆。然而,可以通过替代地利用深度非线性函数和(相对)逆来显著地加强[17、18]。)
现在给出一种方法,通过该方法针对根据我们的方法创建的1对1深度非线性函数f获得这样的逆(如果p=q)或者相对逆(如果p<q)。
对于任何双射函数
存在唯一的函数
如果
并且m<n,则f不能是双射的。然而,f仍然可以是1对1的,这种情况下,存在唯一的相对逆
即,如果忽略S
n中不能通过调用f产生的向量,则f
-1的作用就象能够通过调用f来产生的向量的逆一样。
现在来公开一种用于构造我们所构造的深度非线性函数f的这种相对逆的方法,其中,L和所有R0,...,Rk-1都是1对1的(这种情况下q≥p)。如果p=q,则L和所有R0,...,Rk-1是双射的,并且f的这种相对逆也是f的(普通)逆。
当从线性函数s1构造函数s(见构造的步骤(3))并采用最终函数s2以将s1的输出映射到{0,...,k-1}上时可以应用该方法,其中,s2是按照s1的结果除以k得到的余数计算出的。(如果k是2的幂,可以通过取s1的结果的log2k个低阶位来计算s2,这是一种简便方法,但不是为当前目的实际所要求的)。
定义线性函数L-1和R0 -1,...,Rk-1 -1分别为L和R0,...,Rk-1的相对逆。(因为这些函数是通过矩阵计算出的,所以,它们的相对逆可以通过用高斯消元法等(即,有限域和有限环上的线性代数领域内公知的方法)求解联立线性方程来轻松且高效地获得。)
根据f的构造,有s=s
2оs
1。定义s
1′=s
1оL
-1,这里L
-1为L的相对逆。(因此,(通过在有限域和有限环上的线性代数领域内公知的方法很容易地发现的G
u上的1×q矩阵来计算s′)。定义s′=s
2оs
1′。现在有映成函数
期望的相对逆,或者当p=q时的普通逆为按下述定义的函数
对于任何W∈Gq,设
Wu=extract[0,u-1](W)
Wv=extract[u,n-1](W),以及
其中,j=s′(Wu)。
当p=q时,这只是f的普通逆。当p<q时,该函数行为就象仅仅 中的向量的逆一样。
如果对于s有非严格形式,即,如果它不是按照上述优选实施方式中所述的那样构造的,则仍然可以对双射或者1对1的f进行求逆或进行求相对逆。例如,如果s只是Gu p的元素上的表,如果定义新表s′=sоL-1,则对于f-1的、但使用这种不同的s′了的上述公式仍然是正确的。可以通过贯穿Gu p的全部元素e,确定L(e),并利用s的元素e的内容填充在s′的元素L(e)元素中来获得该新表s′。
利用深度非线性函数来加强10/433,966。当将上面公开的方法结合到[17、18]的方法和系统中时,需要伪装这些函数,因为他们的分量是线性的。即,需要应用[17、18]中公开的简单的编码方法,因为这些编码方法很容易应用于根据针对创建的深度非线性函数的上述方法所构造的分块的矩阵L、R1,...,Rk和s1实现。注意,对于上述创建深度非线性函数的方法,作用之一将是要对选择函数s的输出进行编码,从而同样对用于选择适当的被编码的Ri实现的索引,比如i,进行编码。
与[17、18]中相关的分块的矩阵实现存在三种主要用途。
其中两个类似于密码“白化(whitening)”,但目的是针对增加白盒攻击者而不是针对如普通密码学中的灰盒(侧通道)攻击者或者黑盒(已知明文和/或密文、自适应性已知明文和/或密文)攻击者来说的模糊性。它们类似于应用于灰盒环境以保护智能卡密码实现抵抗不同强度的分析、EM辐射分析等的保护类型,但因为它们是设计用来保护抵抗在白盒环境中操作的攻击者,因此它们涉及到更深的变换。
其他用途只是实现密码中的线性步骤,这种线性步骤在许多类型的块和流密码中是相当普通的。
总之,为以下目的在[17、18]中采用这种分块的矩阵实现。
(1)它们用于“预白化和后白化”;即,用于混合输入和输出以使编码边界向外移动,由此使得根据[17、18]的对实现内部的攻击对于攻击者来说更加含糊不清。
(2)它们用于“中间白化(mid-whitening)”,其中,使得内部计算更复杂,并且通常使内部计算在其计算期间更加均匀地分发信息。这种“中间白化”例如用于[17、18]中§5.2.2节第[0249]-[0267]段中所提议的DES实现。
(3)它们用于实现要被模糊化的功能的线性部分,并且使它们防篡改(在篡改产生几乎不满足攻击者可能有的任何目标的混乱结果的意义下),它们是线性的,例如AES中的MixColumns和ShiftRows步骤或者DES的任何“位置换(bit permutation)”。具体地说,利用4×4 MDS矩阵在GF(28)上的4-向量(即,4字节向量)上计算MixColumns。类似于DES的“位置换”,ShiftRows简单地改变向量中信息的位置而不作其他修改。
如下,可以替换为采用根据上面公开的[17、18]的扩展创建的深度非线性函数。
(1)因为预白化和后白化是对密码实现的输入和输出进行简单地编码,所以可以直接应用根据上述对[17、18]的扩展的宽输入深度非线性函数的构造,以及分块的矩阵和根据[17、18]编码的这些实现的所有部分。这种预白化和后白化无疑使得利用对其白盒实施的已知明文或密文攻击的对密码实现的初始和最终部分(例如密码的初始和最终轮(round))的攻击更费力。
(2)使用按照如上公开所创建的深度非线性函数可以提高安全性。然而,因为深度非线性函数的这种使用还涉及到其逆,甚至当通过与另一线性函数的复合进行伪装时,该函数及其逆的复合会导致函数直到I/O编码之前是线性的,因此向同态映射攻击打开了大门。因此,推荐尽可能更换为使用下面的(3)。
(3)只要可能,应当将用与线性步骤类似但是深度非线性的步骤来替代线性步骤。例如,可以将AES的MixColumns MDS矩阵用深度非线性MDS函数来替代。推荐当这完成时,密码(不是AES而是AES变量)实现成使得加密和解密的实现不在彼此附近发生,因为这会允许同态映射攻击。如果在给定地点仅加密或者仅解密是可用的,则该方法提供了抵抗同态映射攻击的强有力的保护。
(4)此外,只要可行,应当使用非常宽的输入。例如,AES的MixColumns矩阵将32位向量映射到32位向量。232的空间(≈四十亿个输入)上函数的强力逆要求对大约四十亿个元素进行分类。这是巨大的,但在本领域中具有当前设备的当前状态中并不是完全不可行。然而,如果它为两倍宽,则利用当前方法和设备这种分类将是可行的,因为它需要对超过16百亿亿(1.6×1019)项的列表进行分类。
2.7.6.加强10/478,678同时保留其度量值。美国专利申请10/478,678[5]的系统和方法与美国专利6,594,761[2]和6,842,862[4]的系统和方法相关,但[5]添加了某些安全性非常高的数据编码,此外,还提供了一序列相异的数据编码以及通过与[9]中的方法相异的方法测量的这些编码的保护力度。
提议通过这样的度量来测量安全性,该度量尽管随着实现的安全性正向变化,但不提供测量攻击者为了击穿安全性必须执行多少工作量的安全性度量。相反,[5]提供了与工作量相关的度量,该度量为编码之前能够准确地映射到同一编码计算上的相异原始计算的个数。(因为编码计算的含义(meaning)依赖于其发生的上下文,因此会发生这种可能。例如,根据[20],如果可以根据y=ax+b对编码后的值进行编码,则也能根据y′=a′x′+b进行编码,这里a′=3a并且x′=3-1x,3-1是在与用于被保护代码的目标机器的字长度相对应的具体有限环中3的有限环逆。)因此[5]的度量直接测量出试图对利用根据[5]的编码进行了保护的计算的被保护数据上的计算操作进行解模糊的攻击者所面临的搜索空间的大小。
注意到,根据§2.5.3和§2.5.4列出的恒等式或者根据§2.5.1、§2.5.2或[2,4,5,20]中公开的方法得到的恒等式或者在§2.7.7中给出的[20]的扩展中的恒等式或者上述的任意组合,在根据[5]保护数据之后执行替换不能使[5]中提供的度量公式无效。结果最多会是这样的,就试图对这种编码进行解模糊的攻击者所面临的工作载荷方面来说,所提供的保护程度将超过[5]中的公式所给出的数字。
因此这种替换被推荐为增加由[5]的方法所提供的安全性的手段。[5]已经提供了特定的编码方法,例如以余数表示的多项式,其按照上述度量极大地保护。期望是通过扩展上面刚刚描述的[5]的方法,能够构造具有几乎密码的强度的数据和计算编码。
2.7.7.向11/039,817添加多项式编码和MBA恒等式。通过引用将美国专利申请11/039,817[20]的方法合并入§2.7中。现在提供这样的公式,通过该公式,在[20]的模环Z/(2n)上的线性映射可以扩展到更高次的多项式。
多项式可以象线性映射一样地相乘、相加和相减,并且如果具有逆,则在按照如下所述了解决了高次问题之后可以按照[20]中那样进行,但是用2次或更高次多项式的逆替换线性逆,这里线性L(x)=sx+b的逆(如果可逆,即如果s为奇)为L-1(y)=s-1(y-b)=s-1y-s-1b。(按照§2.5.5中所述求出s-1)。随着次数增加,安全性和计算开销也增加。
可逆多项式映射P称为置换多项式,因为它将Z/(2n)的元素映射到Z/(2n)的元素:满足当且仅当(iff)x=y时,P(x)=P(y),即,它定义了Z/(2n)的元素的置换。
高次问题在于:低次置换多项式的复合逆通常为非常高次的置换多项式,通常接近环的大小(即,接近它包含的元素的数量,对于大小为232或264的环确实是非常高的次数)。结果,由于计算逆所需要的大量求幂,使用[20]中方法的二次(次数为2)或更高次模拟的多项式逆极为昂贵。
然而,存在很多低次(即,2、3或4次)置换多项式的特殊形式,其中逆的次数不超过多项式本身的次数。为了形成[20]的线性(次数为1)编码的二次(次数为2)、三次(次数为3)或四次(次数为4)模拟,因此可以利用下列特殊形式的置换多项式。
尽管限制了这种多项式的形式,但是在基于机器字长(通常为Z/(232)或Z/(264))的典型模整数环上的这种多项式的选择数量仍然是非常大的,足以使这种编码安全。
此外,通过使用[20]的系统的这种高次模拟,消除了利用分析形式(诸如,通过高斯消元法求解联立线性方程)的攻击的可能性,由于[20]所提供的编码的线性这可以用来破坏或撤消由[20]所提供的编码。
下面,全部计算是在适当的整数模环(通常在Z/(232)或Z/(264))上执行的。
二次多项式和逆。如果P(x)=ax2+bx+c,这里a2=0并且b为奇的,则P是可逆的,并且
P-1(x)=dx2+ex+f
通过下式定义常量系数
以及
三次多项式和逆。如果P(x)=ax3+bx2+cx+d,这里a2=b2=0并且c为奇的,则P是可逆的,并且
P-1(x)=ex3+fx2+gx+h
通过下式定义常量系数
以及
四次多项式和逆。如果P(x)=ax4+bx3+cx2+dx+e,这里a2=b2=c2=0并且d为奇的,则P是可逆的,并且
P-1(x)=fx4+gx3+hx2+ix+j
通过下式定义常量系数
以及
进一步使多项式及其逆模糊化。还可以通过对上述多项式编码进行后修改、应用根据下述恒等式的替换,使上述多项式编码更模糊化,由此,使得由于这些编码同时在计算内使用多个极为不同的数学域的原因而不能利用诸如MathematicaTM、MatlabTM或MapleTM的工具分析这些编码,所述恒等式是§2.5.3和§2.5.4中这里公开的恒等式或通过利用在§2.5.1和§2.5.2中这里给出的方法得到的恒等式(这使得能够访问实际上无限地并因此而不可思议地巨大的恒等式集合)、或者上述恒等式中的两个或者更多个的某种组合。
2.8.这里扩展的其他系统和方法。在美国专利6,668,325[9]、美国专利6,088,452[19]和美国专利6,192,475[27]中提供了替代通过引用在§2.7中结合进来的软件模糊和防篡改方法的方法。现在来公开这样的方法,通过该方法,为了使这些方法的保护对用于联锁的高级构造的低级构建块有用的目的,可以加强它们的保护。
[9、19]的方法和系统取决于所提供的熵(种下伪随机值流的有效随机信息输入,在应用这些方法和系统时基于该伪随机值流进行编码和保护判定)。因此,它们提供高的静态分集度:每次新使用这些方法和系统通常都产生不同的结果,由此使得攻击者的工作更加困难,因为对利用上述方法和系统改成了受保护的SBE的给定原始未保护SBE的实例进行的攻击必须基于各预生成实例而变化。
2.8.1.加强6,668,325的模糊化。美国专利6,668,325[9]列出了覆盖软件的各个方面(即,控制流、数据流、数据结构和对象代码)的广泛种类的模糊化技术。此外,提议在通过各种度量进行测量时达到期望水平的保护之前应用来自这种模糊化的库的模糊化。实际上,在软件工程中,程序的明确性是目标;[9]应用了度量,但优点在于具有明确性的对立面,即,模糊性,从而[9]提供了用于在保留功能性的同时主动避免和/或逆转通过软件工程控制的可读性和明析性的自动方法(mechanized method)。[9]将模糊化变换的质量分成三个方面:效力,其为就明析性方面来说是被保护软件的“恶劣状态(badness)”,效力是通过诸如秩复杂性的典型软件工程度量来估计的;回弹力,其为通过诸如Mocha的解模糊程序对变换进行解模糊的难度;以及成本,其为由于应用该变换(就较慢的执行和/或较大代码方面来说)的原因添加的开销量。
如在§2.7.6中,现在为[9]提供的加强方法不影响该发明的度量方面的优选实施方式,而是由于同时使用了极为不同的代数域和/或下面公开的其他保护的原因,使得即使利用诸如MathematicaTM、MatlabTM或MapleTM的分析工具也更难以分析被保护的代码,并且使得被保护的代码更主动易损由此抵抗目标导向的篡改,来提供更大的模糊性和防篡改性。
提出了不透明计算值,特别是不透明谓词(predicate)(见[9]第15栏§6.1、第26栏§8),用于通过使条件分支(if)的条件变模糊来保护控制流。在示出了创建不透明谓词的方法(专利本身简述(indicate)的太弱)之后,推荐在[9]第26栏§8.1中(利用混淆,因为混淆分析成本高)和第26栏§8.2(利用多线程中的计算,因为并行程序分析成本高)中的两种更强的方法。这两者都会在更大的代码和更慢的执行方面招致繁重成本。
更好的方法是使用根据下述恒等式的替换来变换谓词,从而使得由于这些编码在计算中同时使用了多个极为不同的数学域的原因而不能够使用诸如MathematicaTM、MatlabTM或MapleTM的工具来分析这些编码,同时在代码块中发生基本上很少的开销并且允许更快的执行,所述恒等式是§2.5.3中这里公开或引用的恒等式、或在§2.5.4中公开的恒等式、或通过采用§2.5.1和§2.5.2中给出的方法而发现的恒等式(其提供了几乎无限的因而不可思议地巨大的可用恒等式集合),或优选上述恒等式中两个或者更多个恒等式的某种组合。
中第21栏§7.1.1建议对程序中的变量进行线性编码,并且在第22栏中的第一段写道:“显然,溢出(overflow)......问题必须解决。或者我们可以确定由于讨论中的变量的范围......没有溢出会发生,或者我们可以改成更大的类型。”因此,很明显,想要在整数上进行线性编码(或者在浮点数上,但这将引发精度问题,该精度问题严重地限制了这样的单纯线性浮点数编码的可应用性)。我们推荐利用具有在§2.7.7中的扩展的[20]中的更高级的整数编码。这避免了[9]中所指出的溢出问题(它们变成了保持模数的实现的合法部分,而不是有待解决的难题),它们保留变量的长度,并且,使用在§2.7.7中提到的基于MBA的替换,它们可以很好地抵抗代数分析和反向工程。
中第23栏§7.1.3提出了将变量x拆分成多个变量,如x1,x2,使得可以使用某种函数x=f(x1,x2)来取回(retrieve)x的值。我们注意到,这样取回x使得代码透露了x的编码,这是不希望的。更好的是允许以编码后的形式进行计算的编码;例如,具有在§2.7.6中的扩展的[5]中的基于中国剩余定理的余数系统(RNS)编码。这总是拆分变量,但是一般不需要为了使用而进行解码。
中第24栏§7.2.1提出了将多个标量变量合并成一个更宽的变量(例如,将两个16比特变量填充到32比特变量的低阶的半个和高阶的半个中。)这并不是非常安全,这是因为任何访问代码都将透露该技巧。更好的方法是使用如在§2.7.1和§2.7.6中所扩展的[2、4、5]的向量编码,其提供多对多映射而不是一对多映射,并且具有高得多的模糊性,同时还支持在编码后的数据上的计算,而不需要为了使用而进行解码。
在第24栏§7.2.2中提出了通过重构阵列来使阵列模糊化:将多个阵列合并成一个阵列,将单个阵列拆分成多个阵列,增加维度数或者减少维度数。我们注意到,通过改变维度数只可以实现有限的模糊化,这是因为,阵列通常由临接的存储器单元条表示;即,在目标代码级,编译后的代码中的阵列已经是一维的了,而不论它们在相应的高级源代码中具有的维度数是多少。
合并阵列如果与对元素地址的置乱组合在一起,则可以提供有效的模糊化。因此,推荐通过使用置换多项式合并阵列并对它们进行寻址来提供比[9]中§7.2.2的方法更强的模糊化。置换多项式是可逆多项式,例如在[20]中用于编码的一次(仿射)多项式或在§2.7.7中添加的次数为2的(二次)多项式、次数为3的(三次)多项式和次数为4的(四次)多项式。这种置换多项式以伪随机的、类哈希表的方式将元素映射到位置,并且采用根据下述恒等式的替换对索引码进行预修改和/或后修改,将使得由于这种索引计算在计算中同时使用多个极为不同的数学域,所以不能够使用诸如MathematicaTM、MatlabTM或MapleTM之类的工具分析这种索引计算,并且因此将提供比通过[9]中§7.2.2教导的而没有在此公开的增强所提供的模糊化强得多的模糊化,所述恒等式是在§2.5.3这里所公开或引用的恒等式、或在§2.5.4中公开的恒等式、或通过采用§2.5.1和§2.5.2这里给出的方法而找到的恒等式(这使得能够访问实际上无限地因而不可思议地巨大的恒等式集合),或上述恒等式中两个或者更多个恒等式的某种组合。
可替换地,可以将阵列合并到根据§2.72被增强了的根据[16]被保护的存储器阵列中,从而利用编码后的数据的附加模糊化益处实现以上所有益处。此外,这种形式的保护不仅适用于阵列,而且也适用于任意数据记录甚至通过指针连接的链接数据结构。
2.8.2.增加安全性的同时降低6,088,452开销US专利6,088,452[19]通过引入覆盖要保护的所有区域的级联(cascades)来使软件(或以诸如VHDL的语言可编程表达的硬件)模糊化。根据[19]的级联是各个输出取决于各个输入的数据流图。程序的每个BB都具有这种级联。级联中的计算本来是任意的;它们的目的是传送熵而不是实现有用的工作。
然后在原始程序中的计算与级联进行缠结(intertwined)并且相互缠结,创建具有极高相互依赖性的极密集数据流图,从而建立邻近逆(proximity inversion)的条件:复制了原始程序的性态(behavior)但是具有大得多并且非常不同的代码的受保护程序中的任何小变化将引起受保护程序性态中的大并混乱的变化。
中的示例使用整数上的多线性(矩阵)运算对运算进行缠结-[19]是主要涉及保护数据项是整数的程序。(这实际上是许多低级程序的情况——在没有浮点代码的情况下可以建立整个操作系统)。
然而,整数计算(包括采用了根据[19]的级联和缠结的那些计算)的问题在于:它们可以超越它们在所选择的目标平台上采用的数据类型的范围限制。因此,根据[19]受保护的程序的实际部署(deployment)需要的整数表示比在根据[19]的保护之前、原始程序中使用的整数表示更大。
因此,优选地在BA[n]上执行所有这种计算,无论该计算处于缠结中或处于级联中,其中n是目标平台的优选字长,这样,在Z/(2n)上执行算术——参见§2.3.2。所选择的缠结矩阵应当是在Z/(2n)上的可逆矩阵(具有奇行列式的矩阵)。因此,溢出不用考虑了,更大的数据表示没有必要了、为了处理多倍精度而增加的代码也避免了,并且该代码比遵循[19]中的教导而没有在此公开的增强的情况更小并且更快。(不过,在原始程序中的计算的全部范围仍然被支持,如通过根据[20]受到保护的程序中的这种计算的支持所示的)。
还可以通过采用根据下述恒等式的替换对缠结后的计算和级联进行后修改可以进一步提高由[19]提供的保护水平,从而使得由于缠结后的计算和级联在计算中同时使用多个极为不同的数学域而不能够使用诸如MathematicaTM、MatlabTM或MapleTM的工具来分析缠结后的计算和级联,所述恒等式是在§2.5.3这里公开或引用的恒等式、或在§2.5.4中公开的恒等式、或通过采用在§2.5.1和§2.5.2中这里给出的方法而找到的恒等式(这使得能够访问实际上无限地因而不可思议地巨大的恒等式集合),或上述恒等式中的两个或者更多个恒等式的某种组合。
2.8.3.通过增大索引复杂度增加6,192,475安全性US专利6,192,475[27]的系统和方法通过以下方式保护基于软件的实体的变量和阵列:改变并增加对其变量和阵列的寻址,使得(A)它们的索引比原始索引更加复杂(可能由于原来不存在索引),并且(B)变量和元素不再在受保护程序中具有固定位置。[27]将其最有效的运算依赖于要受保护的软件的性质:其对于循环地执行许多阵列运算的程序最有效,而不论该循环是明示的还是仅仅是隐含的。
利用仅仅为整数的索引考虑阵列运算,而整数是绝大多数编程语言中对阵列索引的自然理解。通过两种扩展可以使得其保护更强大。
·针对具有以下公开的特性的值k使用在形式为Z/(2n)的模环上的索引
·通过置换多项式第二次对索引进行编码,该置换多项式置换了它们的范围,使得阵列索引A[i1,...,im]变成阵列索引A[p1(i1),...,pm(im)],其中,p1,...,pm是具有以下公开的特性的置换多项式。
前一扩展本身是没有用的。与第二个扩展相结合,它使得阵列索引变得被彻底置乱。
对于阵列的每一维度,或者选择k是素数,优选地至少与该维度一样大的最小素数),或选择k是形式为2n的数,优选地选择使2n至少与该维度一样大的最小的n。在前一种情况中,Z/(k)=GF(k),这样,可以使用在那个域(field)上基本上普通的矩阵计算:如果矩阵的行列式是非零的,则它是精确地可逆的。在后一情况中,Z/(2n)是具有一模数的模环,该模数通常具有比平台的优选计算字所具有的位更少的位,使得(与其中实例公开采用了这种环的其它上下文(contexts)不同),必须通过逐位∧(与)运算来精确地执行模数运算,逐位∧(与)运算将计算的结果与包含除了n个低阶位为1之外全部为0的掩码相与。在这种情况中,由于矩阵只有在其行列式是奇时才是可逆的,所以必须调整线性代数。
以上置换多项式应当是低次的(例如,1次、2次、3次或4次的),但是具有高次的逆,这是因为在置换多项式的该使用中不需要对多项式求逆。这使得多项式的计算便宜并且而它们的逆的计算很昂贵,这正是我们想要的:以低成本给予实质上的模糊性。容易找到这种置换多项式:绝大多数低次置换多项式都具有高次的逆。
这些扩展以及它们的变型中没有任何一个使得[27]的算术或方法(已作必要的修正)的本质方面无效。然而,在循环(明示的或隐含的)期间,它们的组合将变量的存储位置、元素以及它们的相继位置进行彻底置乱,使得对该系统的分析不仅在最坏的情况中是NP难的(NP-hard),如[27]的未扩展版本中的,并且在实际上每种情况中都极难分析。
对于被如此模糊化并且使得在篡改下易损的部分程序的可执行形式,这些扩展以更大的空间和时间开销为代价极大地增强了[27]的安全性。
2.9建立所需要特性。在这一节中,将教导如何建立用于在SBE中安装联锁的示例方法和系统的需求:即,教导如何生成完整的、模糊的并依赖上下文的OE、模糊的并依赖上下文的IA以及必要的、模糊的并依赖上下文的PRE。
2.9.1.生成完整的OE、必要的RPE和转递IA如之前§2.4.5中所述,添加到在预产生BB集合X中计算的预产生计算F的输出扩展(OE),在将它们转换到通过产生BB集合X′计算的生产计算F′时必须是完整的;即,在安装联锁之前,扩展必须被尽可能地约束到正常计算中。
如§2.4.4中所述,被添加到在预消耗BB集合Y中计算的预消耗计算G的RPE,将它们转换成由消耗BB集合Y′计算的消耗计算G′时必须是必要的;即,RPE必须以下述方式与在安装联锁之前出现的正常计算相结合:使得如果rpe基于生产F′和传递R′所预期的输入没有受到篡改的话,则除了某些极不可能的偶然情况以外,只能发生正常功能。
如果考虑通过预产生BB集合X计算的预产生MF F,则可能存在通过在X中计算F所产生的值,所述值被通过预消耗BB集合Y计算的预消耗MFG消耗(有可能在由预传递BB集合V计算的预传递MF R进一步修改之后)。这些值的计算对于通过X进行的计算F是完整的,并且通常,很可能在通过V进行的R的计算的进一步修改之后,它们对于通过Y进行的G的计算是必要的。
情况1:没有或弱X→Y数据依赖性。如果不存在或没有足够多的这种在预产生BB集合X中计算出的并且随后在预消耗BB集合Y中被采用(有可能在预传递BB集合V中被进一步修改之后)的值,则我们必须添加或增大这样的依赖性的数量。在这已经被完成到足够的程度之后,已经建立了强X→Y数据依赖性,并且可以继续进行到如以下的情况2:强X→Y数据依赖性中所述。
为了增大X→Y据依赖性,我们可以以下述的专门方式来采用[20]的编码系统,或在§2.7.7中教导的其扩展。
在[20]的编码系统中,对于BA[n]中的整数值x,其中,n是目标执行环境的正常字长,将x编码为x′=sx+b,以保存x中的全部信息位,其中s是缩放比例(scale)并且b是编差,b是任意的,但s必须是奇的。[20]教导了如何利用这样编码后的值(其中不同的值具有不同的缩放比例和偏差)进行计算而不对它们进行解码,以合并C或C++的所有正规内置算术、移位和逐位运算。§2.7.7公开了将[20]中的编码扩展成非线性次多项式的方法。
为了增大X→Y数据依赖性,利用X BB集合中计算出的值作为[20]的原始版本或如§2.7.7中所公开的其扩展到二次、三次、四次多项式中的偏差值(就具有变量x、系数x0的多项式而言),因为这避免了对动态地计算逆的需要。然后,可以使用从X中获得的偏差来对Y中的计算进行编码,藉此,通过使用X中计算出的足够多的值,或如上所述从它们推导出的值,作为用于根据[20]对在Y中所使用的值和所执行的计算进行编码的偏差,可以创建任意强的X→Y数据依赖性,并且因此能够满足使用以下情况2:强X→Y数据依赖性方法的先决条件,然后由此继续下去。
在采用[2、4、5、17、18]中的一个或多个的编码来替代采用[20]的编码的情况中,可以替代地或者附加地使用这样的类似方法,该方法使用预产生BB集合X中的值或仅仅是从它们推导出的值来提供编码的系数。通过对X中计算出的足够多的值或仅仅从X中所计算出的值推导出的附加值进行此处理,并且将它们用作对Y中的值和计算进行编码的系数,能够创建任意强的X→Y数据依赖性,并且因此能够满足用于使用下面标题为情况2:强X→Y数据依赖性中的方法的先决条件,然后,由此继续下去。
通过采用对在[2、4、5、17、18、20]中列出的那些编码进一步修改而得到的编码,可以进一步增加上述方法中的任意方法或全部方法,上述修改采用了在§2.5.3中公开或引用的恒等式,或者借助于利用在§2.5.1或§2.5.2中这里教导的方法而创建的恒等式,或者在§2.7.7中给出的[20]的扩展中找到的恒等式。通过用于在X和Y中的足够多的计算的这种方式,能够创建任意强的X→Y数据依赖性,并且因此能够满足用于在以下标题情况2:强X→Y数据依赖性下的方法使用的先决条件,然后,由此继续下去。
最后我们进行X中的计算,并且通过利用下述恒等式使用不同的表达式来创建这些相同计算的附加版本,所述恒等式是§2.5.3中公开或引用的恒等式、或§2.5.4中公开的恒等式、或使用在§2.5.1和§2.5.2这里教导的方法创建的恒等式、或[2、4、5、20]中公开的恒等式、或§2.7.7中给出的[20]的扩展中得到的恒等式。这样的附加版本是与原始版本一样完整的:通过检验代码绝对无法区分原始版本和附加版本。在这点上,这些计算产生相同的结果,但是我们应当将它们放在新的、分离的值中。
然后,通过使用成对的值中的原始值和替换值,可以容易地增加Y中的表达式,以不发生净变化的方式利用这些值,所述成对的值中一个是X中原始产生的值,一个是通过利用上述MBA恒等式如上所述地添加的值。在以下所述的进一步的模糊化步骤之后,这些利用将被很好地隐藏。此外,由于没有净效果的增加采用了X中的原始值和附加值两者,所以附加的优点:对计算的篡改将通过以下方式使得Y中的计算失败:造成原始值和恒等式所添加的值之间的差,从而使得Y中表达式增加具有净效果,从而随意地修改Y中的原始计算以计算出不同的、随意结果。
通过充分地创建这种增加,可以创建任何所需水平的X→Y数据依赖性,从而满足用于采用以下情况2的方法的条件,然后,由此继续下去。
简单而言,我们还可以采用以上方法的任何组合来实现强X→Y数据依赖性的状态,并且之后根据以下情况2继续进行。
情况2:强X→Y数据依赖性如果存在足够的在X中计算出的并且在Y中被采用(可能在V中进一步修改之后)的这种值,则可以定义J为这些值的副本的状态空间、K为这些副本在随着它们的原始值被R修改而被修改之后的状态空间,以及G按如下所述利用副本。
然后,得到
其中x
+∈K是通过对所选择的值再次执行计算以产生K中的复制结果而获得的。当然,此时,输出扩展是不安全的,因为用于产生x
+的计算是来自通过X的F的现有子计算复制过来的。我们将在以下所述的进一步的步骤中解决这个问题。(注意x
+可以包括许多变量的值,因为它是程序的状态空间的某些部分的副本。)
复制的值是优选实施例,但是还存在其他信息保留替换例,诸如,x
+=-x、
x
+=x+k或x
+=x⊕k,其中k是常量,
和⊕表示逐位运算,并且+是以目标硬件的自然二进制补码模环执行的。对于本领域技术人员,许多这种信息保留替换例是显而易见的——实际上如此之多以致很容易在联锁安装期间基于随机输入来在算法上选择它们。
以上已经提到了通过复制计算来复制值。对于任何被复制的值c,明显的是,代替复制c,可以替换为复制作为计算c所使用的输入的值,如i1,...,ik,即使这些输入中的某些输入是在X中的代码之前的计算的副本。这允许我们可以关于复制什么有更多的选择,从而增大在安装联锁时所的选择的输出扩展FOE的模糊性。
选择至少最初与原始值等同的被复制的值(或至少信息保留替换值)的目的是降低意外匹配的可能性。该方法的替换例可以是选择相关的值:替代创建值v的副本c,可以创建与v的值相关的值r---例如,确保r<v或r>v或r≠v或v mod r=5等等。这些是合法并且可行的选择,但是在优选实施方式中,根据以下理由选择等同的值(或最最至少是等价的信息)。如果考虑以某种方式与v相关的值v′,则之后,通过篡改而偶然实现该关系的可能性随着该关系变得越有限制性而减小。BA[32]的随机选择数平均在232≈4.29×109次随机试验中只有一次与v匹配。然而,BA[32]的随机选择数将通常会比v大或比v小,无疑时常为:即,这些关系不是优选的,因为它们不是很有限制性的。BA[32]的随机选择数可以使得v mod r=5非常常见:即,在|r|次随机试验中就会有一次,这通常比232次随机试验中一次要经常得多。为了这个原因,优选实施方式使用复制后的值(或信息保留替换值),使得篡改实际上必定引起与预期的复制后的值或预期的替换值失配。
称状态x为通过由V中的BB对R的计算而修改的状态v。然后继续扩展数据状态,由于R(x)=v,得到Ragg(x,x+)=(v,v+),其中,v+是在x+中按照通过R处理复制后变量的原始值的方式处理复制后变量的结果——此外,仅复制那些计算,但是将它们应用于副本而不是原始的(如果R未影响它们,则在每种情况中v+=x+,这样K=J。)
此时,我们必须将通过BB集合Y进行的预消耗计算G转换成消耗计算
寻求以对x与x
+之间的关系或v与v
+之间的关系的扰乱将使得计算G
RPE失败的方式来完成这一处理。
用于完成此的优选方法利用以下事实:其状态是在v+中被捕获的变量的内容与在V中所捕获的相应变量的状态(在此时)是等同的,其中,v+变量是v变量的子集。
当然,如在讨论FOE输出扩展的生成中所述,应采用除了相等以外的一个或多个关系,在这种情况中,我们会调节RPE的生成,以只有一个或多个替换关系成立时才正常运算,而不是只有相等关系成立时才正常运算。或者,如果我们以替换形式保留了信息而不是可交换地使用x与x+,如果有等式x+=f(x),则我们可以自由地用f-1(x+)替换x。例如,如果x+=x+k,则我们可以自由地用计算(x+,-k)来替换值x。
现在,如上面在§2.5.3中的第(3)项中所注意到的那样,当针对两个变量v
1、v
2时,具有v
1=v
2,还具有v
1∨v
2=v
1∧v
2=v
1=v
2、v
1-v
2=v
1⊕v
2=0,
(带符号的),并且通过简单的代数操作、或通过与下述恒等式相结合可容易地推导出的很多其它恒等式,所述恒等式是在§2.5.3中所公开或引用的或在§2.5.4中所公开的恒等式、或通过在§2.5.1或§2.5.2中所公开的方法而得到的恒等式、或在[2、4、5、20]中所公开的或在§2.7.7中所给出的[20]的扩展中所得到的恒等式。
假设v1是v的一部分而v2是v+的一部分。则可以产生很多只有在保持了v1和v2的相等性时才等同的表达式。通过使用随机选择的v1和v2或使用在G中发生的v1和v2二者的混合(比如,在G中初始只使用v1)在这些表达式中进行自由地替换,并且使用多个不同的v1、v2对来进行这种替换,使得很多在G中使用的变量都受到影响,就得到了G的变型GRPE,该变型GRPE只有在各v1、v2对中v1=v2时才正常工作---否则,它将几乎肯定失败。注意,篡改GOE或Ragg中的任意一个都会产生v1≠v2的v1、v2对。因此创造了所需要的必要的RPE、GRPE。
注意:上面谈及了使用原始值以及它们的副本。(更通常地,可以用原始值及它们的相关值来进行替代,或者用对原始值及副本的计算的输入或与那些输入相关的值来进行替代。)代替使用原始值及它们的副本,还可以采用通过这些值而计算出的值及其副本,即,使用这些值作为输入,即使在执行了Y中的代码后计算出了这些值。也就是说,可以使用来自X′的副本以创建Y′中的更多副本,并且之后在计算中采用那些副本(或可能的其它形式的相关值)以招致在发生篡改时非常可能失败。这给予了在篡改的情况下在产生代码失败中采用什么拷贝更多的选择,由此提高了在安装联锁时所选择的RPE GRPE的模糊性。
生成IA。已经简要地提及了把由BB集合V所执行的预传递计算
转换成计算
中,可以执行以下任意步骤。
(1)如果R已经修改了在X中计算出的值,并且在Y中采用了那些修改,则如果复制那些值以根据F创建完整的OE FOE,则可以复制R中相关的计算以获得Ragg,并且之后在GRPE中可以采用来自Ragg的复制,同时随机选择使用原始值和副本值,从而使得RPE GRPE对于G的功能性的保持来说是必要的。该方法的应用不考虑计算的复杂性以及通过预传递BB集合V的控制流。
(2)如果R没有修改在X中所计算出的、希望复制以由F创建完整的OE FOE的值,则可以简单地保持在计算R的BB集合V中的计算不变。这意味着K=J且Ragg=[R,idJ],其中J包含复制的值。这种另选方法(什么都不做)的应用不考虑计算的复杂性以及通过预传递BB集合V的控制流。
(3)如果R没有修改在X中所计算出的、希望复制以由F创建完整的OE FOE的值,则可以因此向V添加计算,使得对于任意给定的v1、v2对,其中v1是计算F的原始结果,而v2是所添加的副本,而且可以向R增加一对计算,使得v1用于多个计算,但这些计算最后仍然产生v1,而v2用于不同的一组计算,但在最后所述不同的一组计算仍然产生v2。即,针对v1和v2执行没有净效应的相异计算。然后,仍然具有K=J且Ragg=[R,idJ],其中J包含复制的值,但在以下所描述的进一步模糊化步骤之后,或者可能就不是这种情况---尽管仍然保留了全部功能---或者,如果仍然是这种情况,则很不明显。这种另选方法要求能够分析在V中添加的涉及v1、v2对的计算的净效应。如果通过V的数据流和控制流足够复杂,则这种分析会非常困难。因此,该方法仅应用于这样的情况:其能够被限于对BB集合V中相对于控制流和数据流来说足够简单的部分BB的修改,以允许可靠地添加这种没有净效应的计算。(可允许的复杂性程度因此将取决于可用编译器的数据流分析及控制流分析工具的完善度)。与以上另选方法(1)和(2)不同,该方法不总是适用。
(4)如果R没有修改在X中所计算出的、希望复制以由F创建完整的OE FOE的值,则可以因此向V添加计算,使得针对任意给定的v1、v2对,其中v1是计算F的原始结果,而v2是所添加的副本,而且可以向R添加一对计算,使得v1用于多个计算,这些计算最后产生w1,其中一般w1≠v1,而v2用于不同的一组计算,这些计算最后产生w2,其中一般w2≠v2,并且其中根据w1可以容易地计算出v1并且根据w2可以容易地计算出v2。即,针对v1和v2执行具有净效应的相异计算,但仍然以可以计算v1和v2的变相形式w1和w2保留了v1和v2。
之后当产生GRPE时修改代码,因而该代码分别用针对v1的关于w1的表达式的使用和针对v2的关于w2的表达式的使用替代了v1的使用以及v2的复制使用。
之后将很可能具有K≠J,且Ragg=[R,S],其中S执行上述的根据v1、v2来计算w1、w2。当然,这不仅是对一个v1、v2对及其相对应的w1、w2对来说是成立的,而且还已经确定了对所有v1、v2对来说是成立的,并且对所有它们相对应的w1、w2对来说也是成立的。
在下面描述的模糊化步骤后,尽管仍然保留了全部功能,但是这些计算可以不再根据在各种对中的值w1和w2来针对v1的v2产生相同的值-或者,如果产生了相同的值,则情况将是不明显的。
如上面的另选方法(3)那样,这个另选方法要求能够分析添加到V的涉及v1、v2对在这种情况下以产生w1、w2对的计算的净效应。如果通过V的数据流和控制流足够复杂,则这种分析会非常困难。因此,该方法仅适用于这样的情况:其能够被限于对bb集合V中相对于控制流和数据流来说足够简单的部分BB的修改,以允许可靠地增加这种具有具体净效应的计算,即,根据已知的保留值公式计算w1、w2对的计算。(可允许的复杂性程度因此将取决于可用编译器的数据流分析及控制流分析工具的完善度)。与以上另选方法(1)和(2)不同,该方法不是总适用。
上面的方法(3)和方法(4)受到这样的限制,即,只有在以下两种情况下才可以采用这两种方法,这两种情况分别是:在预传递BB集合V中的数据流和控制流复杂性低到足够允许可预测地添加对由FOE产生的输出-扩展副本对不具有净效应的计算的情况,或在预传递BB集合V中的数据流和控制流复杂性低到足够允许可预测地添加具有分别以变相形式w1和w2保留了输出扩展副本对的值v1和v2的已知净效应的计算的情况。
使用在§2.10.2中所描述的方法可以克服这种限制。
2.9.2.使OE、IA、以及RPE模糊且依赖上下文。在已经了安装根据§2.9.1的联锁的基本结构之后,现在必须使联锁代码模糊,使得难以分析并模糊它的功能,以及进一步添加它的抗篡改性,而且必须使联锁代码依赖上下文,使得它与周围的代码相类似。
关于所有联锁组件。实现这的优选方法是向所添加的用于创建联锁的代码以及这些代码附近的其它代码都应用相同的注入防篡改的一种或多种方法,其中防篡改的强度从针对联锁代码自身以及紧邻的附近中的代码的较高程度到针对离联锁代码越远的代码的强度越降低而变化,直到最终抵达较大的SBE代码块,该较大的SBE代码块由于离联锁代码足够远从而不需要特殊的保护来保护所安装的联锁,而可以保持不变。
对于所有[2、4、5、9、19、20]中的防篡改方法或者它们在§2.7和§2.8中的扩展来说,通过变换较大量或较小量的计算、变换较大量或较小量的值、以及通过选择具有较高或较低开销并且相对应地较高或较低的安全性的变换,可以从高到低地改变保护的强度。[5]提供了对这种选择的分析。这些方法适用于所有联锁组件。
通过将以上[2、4、5、9、19、20]或者它们在§2.7和§2.8中的扩展中的任意或全部与附加的数据和计算模糊化进行组合,可以获得适用于所有联锁组件的附加防篡改方法,其中所述附加的数据和计算模糊化是通过向被采用以创建[2、4、5、9、19、20]的数据和计算编码的恒等式、或在§2.7.7中给出的[20]的扩展中所提供的恒等式添加任意数量的在§2.5.3中所公开的或引用的、或在§2.5.4中所公开的、或由§2.5.1或§2.5.2中的方法所产生的恒等式而获得的。
或者,通过在将要被模糊化的代码中执行较大或较小量的表达式替换,可以获得较大或较小强度的模糊化,其中替换以根据以下恒等式的等同表达式来替代表达式,这些恒等式是在§2.5.3中公开的或引用的恒等式、或在§2.5.5中公开的恒等式、或由§2.5.1或§2.5.2中的方法所产生的恒等式、或者为了创建[2、4、5、9、19、20]的数据和计算编码而采用的恒等式或它们在§2.7和§2.8中的扩展。通过这种方式可得到的这种恒等式的数量随着表达式的大小迅速地增长,从而恒等式的供应是实际不受限制的。再次,这种模糊化可应用于所有联锁组件。
防篡改优选的是仅仅模糊化,然而,防篡改不仅意味着模糊性而且还意味着在注入错误攻击和其它修改代码的攻击下的混乱性态。
那些熟悉编译器代码变换的人和熟悉代数运算及推导的人能够容易地操作和扩展这种形式的模糊化。
针对传递IA。如果攻击者理解传递IA的控制流,则对于传递IA的攻击更加容易。因此,优选地使用根据§2.7.3所扩展的、可能具有根据§2.7.4的开销减少(其中,资源的约束要求这种减少)的[3]的方法和系统,或者应用[9]的控制流保护(优选地带有§2.8.1中公开的改进),来对包含传递IA的BB中或在它们附近的BB中的控制流既进行模糊化,也使其防篡改。
2.10.联锁方法的变型。上面所教导的联锁的基本系统和方法存在很多变型,通过扩大能够以联锁的形式来构建的安全属性的数量,这些变型极大地增大了联锁的基本系统和方法的效用和适用性的范围。以下提供了很多的这种变型。
2.10.1.合并联锁。假设已经经由间插预传递BB集合V将预产生BB集合X联锁到预消耗BB集合Y,由此将X转换成产生BB集合X′,将V转换成传递BB集合V′,并且将Y转换成消耗BB集合Y。
注意,绝对没有任何东西能够阻止选择新的预产生BB集合X,采用Y′作为新的预消耗BB集合Y=Y′,并且选择间插在X和Y之间的适当的新的预传递BB集合V,并且之后将X联锁到Y,由此将X转换成产生BB集合X′,将V转换成传递BB集合V′,并且将Y=Y′转换成消耗BB集合Y′=Y″。
这把两次再联锁到Y扩展成重复任意次数地再联锁到Y,因此能够将X1联锁到Y,并且然后将X2联锁到Y′,并且然后将X3联锁到Y″,等等。
将这种重复联锁到程序的相同部分的连续联锁称为合并联锁。
2.10.2.连接的多个联锁和联锁链接。在此处教导的联锁链接方法在下述任意情形中都是有用的:通过对一连串的BB集合进行联锁以约束(tie)在一起是有用的,其中在任意点进行篡改将造成随后在整条链上的失败,由此阻止黑客可能试图破坏原始代码的目的的任何打算。
另外,它可用于规避用于产生IA的方法(3)和方法(4)的限制,该方法(3)和方法(4)只有在下述两种情况下才可以被采用:在预传递BB集合V中的数据流和控制流复杂性低到足够允许可预测地添加对由FOE产生的输出-扩展副本对不具有净效应的计算的情况,或在预传递BB集合V中的数据流和控制流复杂性低到足够允许可预测地添加具有分别以变相形式w1和w2保留了输出扩展副本对的值v1和v2的已知净效应的计算的情况。
当使用在下面教导的方法来链接联锁时,优选通过下述来使链接的联锁的所有组件(不只是传递IA中的BB)以及它们紧邻的附近中的BB的控制流既模糊又防篡改,来保护它们的链接的控制流:使用根据§2.7.3扩展的、可能具有根据§2.7.4的开销减少(其中,资源的约束要求这种减少)的[3]的方法和系统、或在[9]的方法和系统(优选地具有§2.8.1中公开的改进)的控制流保护。
为了将联锁链接起来,注意到可以使正被联锁的关系是可传递的,使得如果以下面所描述的连接方式将X联锁到Y,并且将Y联锁到Z,则X有效地联锁到Z。
为了将从计算F的X到计算G的Y的联锁与将从计算G的Y到计算H的Z的联锁连接在一起,注意到,通过关于在F的OE中初始计算的并然后在由Z所计算出的G的RPE中所采用的多对值的恒等式来将X基本地联锁到Y,所述在G的RPE中是以造成所述多对值中元素不同的篡改将使得GRPE无法保留G的功能性(即篡改将使GRPE的计算失败)的方式采用了所述多对值。为了保证联锁的传递性,之后,必须对来自GRPE的多对值进行复制以创建GRPE:OE,使得在GRPE:OE中计算出的新的副本对取决于如果上述的对不同在GRPE中就会失败的计算,即,以在新的GRPE:OE计算中如果输入的对不同则新的即将输出的对很可能将不同的方式,使用由计算接收到的对中的元素来计算新的副本对。当这完成以后,一旦安装了X到Y的联锁和Y到Z的联锁,G′中的失败将触发H′中的失败。
因此为了实现X与Z之间的联锁,可以用连接到前面的X到Y的联锁的连接的联锁来更换为伪造X与Y之间的联锁并且之后将所产生的经修改的Y联锁到Z。这可以应用于任意的联锁链:假设在BB集合序列X1,...,Xk中,如果能够创建Xi到Xi+1的连接的联锁,这里i=1,...,k-1,则能够将X1联锁到Xk。在针对安装联锁而描述的方法中,没有任何东西能够阻止以这种方式将连接的联锁链接起来。
例如,如果X与Y之间的BB集合V太复杂而不能分析,则可以通过以连接的联锁将从BB集合X到BB集合Y的路径中的中间阶段联锁起来,来代替分解通过V的复杂路径,由此将预传递BB集合的数据流和控制流复杂性程度降低到以上方法(3)和方法(4)可适用的程度。
2.10.3.多消耗和联锁树。一般地,在如上面的§2.4到§2.9中所描述地那样构建基本联锁的过程中,存在这一个预消耗BB集合Y,将对该预消耗BB集合Y进行修改以创建消耗BB集合Y′,其中,在包含的程序中将被修改以创建产生BB集合X′的预产生BB集合X是BB集合Y的控制集。因此,在X中的BB与Y中的BB之间的路径上存在着一个包含零个或更多BB的预传递BB集合V,在安装联锁的过程中,可能需要或可能不需要将该预传递BB集合V修改成传递BB集合V′。
然而,没有任何东西强迫我们只能拥有一个这种预消耗BB集合Y。可以拥有任意数量k个这种BB集合Y1,...,Yk,其中,任意数量(可能交迭,可能为空)的相应预传递BB集合V1,...,Vk,只要满足在§2.4.2的开始处给出的条件且BB集合Y1,...,Yk不交迭即可。
当使用在下面所教导的方法创建了联锁树时,优选通过下述来使联锁树中的联锁的所有组件(并不只是传递IA中的BB)以及它们紧邻附近的BB中的控制流既模糊又防篡改,来保护链接的控制流:使用根据§2.7.3扩展的、可能具有根据§2.7.4的开销减少(其中,资源的约束要求这种减少)的[3]的方法和系统、或使用[9]的方法和系统所提供的控制流保护(优选地具有在§2.8.1中公开的改进)。
为了在X与Y1,...,Yk中的每一个之间安装联锁,以一般的方式创建X的计算F的OE FOE。还可以基于在FOE中产生的副本值,以一般的方式创建RPE GRPE,1,...,GRPE,k中的每一个。
一个新增加的问题是从X到Yi的路径可以与从X到Yi的路径相交迭,其中i≠j。在该情况下,可以是这样的,即,在交迭的BB集合和Vi与Vj中的代码具有足够简单的控制流和数据流,使得对于上面给出的关于在经修改的Vi中产生Ragg,i计算和在经修改的Vj中产生Ragg,j计算的方法(4)来说是简单的。否则,如在§2.10.2中所描述地那样,可以应用链接以降低复杂性,或者可以使用在不修改Vi与Vj的情况下构建联锁的方法(3)。当使用了该方法时,由于预传递计算的复杂性对于安装联锁的难度来说没有净效应,因此可以允许其复杂性任意高。
通过将该变型与在§2.10.2中所教导的联锁链接相结合,能够创建联锁的BB集合的树,使得可以以联锁的方式将很多程序执行点约束在一起。
2.10.4.依赖于条件的联锁。在一般的编程语言中存在很多在计算过程中使用条件值来引导控制流的结构。
例如,在图4(a)中,使用类似C或C++的代码,如果c为真,则控制从U流到V,而如果c为假,则控制从U流到W。在图4(b)中,如果i=v1,则控制从U流到V1,如果i=v2,则控制从U流动到V2,...,如果i=vk,则控制从U流到Vk,并且如果i≠vj,j=1,...,k,则控制从U流到W。
能够修改§2.10.3中的联锁变型以如下地利用这种条件控制流以及相关的条件。
使用[2、4、5、9、19、20]的恒等式、或在§2.5.3中公开或引用的恒等式、或在§2.5.4中公开的恒等式、或使用§2.5.1或§2.5.2的方法可以计算出的恒等式、或者在§2.7.7中公开的恒等式、或者这些恒等式的任意组合,能够容易地创建用于预产生BB的计算F的OE,其以下述方式来计算条件:只有条件为真时,才存在相等的副本对;只有条件为假,才存在相等的其它的对(例如,如果c为真,p=q且q≠r,以及如果c为假,则p≠q且q=r)。假设当c为真时,控制流向BB集合Y1,而当c为假时,控制流向Y2。
最好不要从条件本身开始,而是检查用于计算在计算这些条件时使用的值(或者用于计算在计算这些条件时使用的值的值,等等---添加的间接越多层,就越安全,但是开销也就越大)的数据。例如,如果条件是“x<y”,其中存在之前的赋值“x=4*a+(b & 1)”以及“y=b+9-(a|0xFF)”则可以使用以下条件代替:
(4*a+(b & 1))<(b+9-(a|0xFF))
(由于把一个条件的操作数的源“提升”到在代码清单中一般显示在页的较高位置处的较早的计算,所以将这种把在后的操作数移向在前的计算同时保持等效性的处理称为源提升。)
之后,在预消耗BB集合Y1和Y2中,创建Y1的RPE,其取决于当c为真时匹配的对,诸如p,q,并且创建Y2的RPE,其取决于当c为假时匹配的对,诸如q,r。结果,任何通过破坏条件c的正常效果来干扰从X到Y1或Y2的流的尝试都将很可能失败。
类似地,使用[2、4、5、9、19、20]的恒等式、或使用在§2.5.3中公开或引用的或在§2.5.4中公开的恒等式、或使用§2.5.1或§2.5.2的方法可计算出的恒等式、或在§2.7.7中给出的[20]的扩展中所给出的恒等式、或这些恒等式的任意组合,可以容易地创建预产生BB的计算F的OE,其以下述方式计算带索引的条件(如图4a中的i):即,只有在索引值是特定的常量时或只有在索引值不是特定的常量时,才存在着相等的副本对,并且使用这些副本对将U(见图4(b))联锁到Vi,使得如果执行Vi则依赖于具有i=vi,i=1,...,k而使用对以及将U联锁到Z使得依赖于具有i≠vj,j=1,...,k来使用对。结果,任何通过破坏索引条件i的正常效果来干扰从U到V1,...,Vk或W的流的尝试都将失败。
2.10.5.取决于条件的合并。在上面的§2.10.4中,公开了用于保护分支不受诸如分支干扰(branch jamming)或通过篡改来破坏正常的控制流的其它方法的攻击的方法。在公开的方法中,分支继续存在,但是如果其控制流受到篡改,则执行将具有很高的失败几率。
现在将公开该方法的变型,其中,取消了分支,并且呈现在分支的可能的目的地处的代码被合并在一起。
在上面的§2.10.4的方法中,创建了在各种目的地的代码,只有当由原始条件所创建的值匹配在没有受到篡改的更改的情况下到达分支目的地中的代码时,这些代码才正常地发挥作用。(优选地是匹配(即,相等),但是也可以使用其它关系。)
当出现条件二元分支时(如在图4(a)中的if语句那样),一般使用在U中提供的值所计算出的条件c控制执行V或W中的哪一个。依次,这对在Z及其后中使用的值产生了影响。因此,if语句的效果最终是确定从Z及其结果来看对程序的变量的状态的作用。如果可以在不使V和W严格地相互替换的情况下而产生相同的条件效果,则可以在不需要由c控制的条件分支的情况下产生if语句的效果。
如图4(b)那样,当出现条件索引的多路分支时,通常使用在U中提供的值所计算出的条件索引i控制执行V1或V2或...Vk或W中的哪一个。由此,这将影响在Z及其后中使用的值。因此,switch语句的效果是最终确定从Z及其结果来看对程序的变量的状态的作用。如果可以在不使V1,...,Vk,W严格地相互替换的情况下而产生相同的条件效果,则可以在不需要由i控制的带索引的条件分支的情况下产生switch语句的效果。
两个占有备选对象。首先,将描述该两个备选对象情况下的方法,如在图4(a)中那样,在C或C++中的if语句中,这两个备选对象都包含了计算。
在§2.5.3中公开了一些方法并引用了其它方法,用于将条件转换成表示真的值1和表示假的值0,或者另选地,将条件转换成表示真的值
(全部位都为1,带符号的或不带符号的)=-1(带符号的)和表示假的值0。
一旦实现了这,就可以容易地对计算进行组合,使得,实际上,当条件为真时,通过乘以1来保留持如果条件成立要执行的计算,或当条件为假时通过乘以0来取消(使变为零)如果条件成立要执行的计算,或者另选地,当条件为真时,通过用
(全部位为1)进行∧来保留如果条件成立要执行的计算,或当条件为假时通过用
(全部位为0)进行∧来取消(使变为零)如果条件成立要执行的计算。在计算结束时,通过接受两个备选对象的结果(其中一种结果当应用了以上方法时具有正常的值,而另一种结果通过应用以上方法已经变为零),并且使用+、∨或⊕进行组合来选择保留的结果,从而可以最终得到单一结果,该单一结果对于选择应该产生结果的哪个备选对象集的条件的状态而言是正确的。
三个或更多个占用备选对象。将描述在超过两个备选对象的情况下的该方法,其中每一个都包含有代码,如在图4(b)中那样,在C或C++中的各备选对象都包含了计算的switch语句中。
在§2.5.3中讨论了一些方法并引用了其它的方法,这些方法用于将条件转换成表示真的值1和表示假的值0,或者另选地,将条件转换成表示真的值
(全部为1位,带符号的或不带符号的)=-1(带符号的)和表示假的值0。
在上面给出的方法中,或者保留与控制条件c为真相对应的计算并取消与c为假相对应的计算,或者取消与控制条件c为真相对应的计算而保留与c为假相对应的计算。明显地,这等同于具有两个条件c1和c2,其中,当且仅当(iff)c=真时具有c1,以及当且仅当(iff)c=假时具有c2。然后,如果c1为真则保留V的计算,而如果c1为假则取消V的计算,并且如果c2为真则保留W的计算,而如果c2为假则取消W的计算。最后,使用∨、⊕或+将相对应的值与仅仅在Z或其后中能看到的保留的计算的结果结合起来。
为了处理三个或更多个备选对象,根据在上面段落中的方法来继续,但是具有以下的变化:具有与处理多路选择所需要的条件一样多的条件,该多路选择在合并操作之前是通过分支来执行的。即,当且仅当(iff)i=vj时,具有cj j=1,...,k,并且当且仅当(iff)(i≠v1)且...且(i≠vi)时,具有ck+1。可以如在§2.5.3和§2.5.4中所讨论的那样来计算任何这种条件的一位或全位表示。注意,c1,...,ck+1中正好只有一个为真,而其余的都为假。因此可以保留V1,...,Vk,W中一个的计算结果中的其中一个,并且取消V1,...,Vk,W的其余的所有计算结果。然后只需要采用针对特定的值的各组相对应结果(如,r1,...,rk+1)并使用∨、⊕或+来将它们结合起来;即,通过计算r1∨...∨rk+1或r1⊕...⊕rk+1或r1+...+rk+1,并且由于只存在ri中的被保留的一个(如,rj),因此,结果是在消除来自k个被取消的计算集的任意结果的同时产生单个被保留的计算集的结果。
在C或C++中,备选对象条件可以采用比图4(b)所示形式更加复杂的形式。允许具有多个case-标签,一个标签接着一个标签,使得对于特定的Vj而言,例如,选择执行Vj的条件是(i=vj,1)∨(i=vj,2)∨...∨(i=vj,m)。通过以用于更复杂条件的计算来替换用于条件i=vj的计算,采用在§2.5.3中公开的或引用的或在§2.5.4中公开的方法,可以容易地处理这种条件。一旦完成了处理,就可以像处理之前讨论的较简单条件那样来处理利用该条件进行的保留和取消。
两个备选对象:其中一个为空。还具有诸如图5(a)中的if-语句那样的if-语句,即,除了else-备选对象为空以外,该if-语句与图4(a)中的if-语句相似。在图5A中,示出了不具有else-代码的条件if语句的伪码(即,一种或者执行then-代码或者不执行任何代码的if语句)。
至于上述的两个占用备选对象,使用在§2.5.3中所公开或引用的方法,将条件转换成表示真的值1和表示假的值0,或者另选地,将条件转换成表示真的值
(全部位为1,带符号的或不带符号的)=-1(带符号的)和表示假的值
(全部位为0)。
以与以上针对两个占用备选对象差不多的方式来继续,但是存在这样的差异:对于两个占用备选对象而言,当c为真时,保留来自V的值而取消来自W的值,而当c为假时,取消来自V的值而保留来自W的值;然而,对应仅一个占用备选对象而言,当c为真时,保留在V中计算出的新值而取消从U引入的旧值(不管是在U自身中计算出的还是在执行U之前计算出的),而当c为假时,取消在V中计算出的新值而保留从U引入的旧值。
三个或更多个备选对象:一些为空。除了并不是对所有备选对象都被占用以外,在图5(b)中例示的这种情形与在图4(b)中例示的情形相似。图5B示出了用于与图5A中的语句相似的语句的伪码,但是其中,具有代码的备选对象和不具有代码的备选对象之间的选择是使用了带索引的选择(即,通过使用具有多个备选对象的switch语句)而做出的,而不是像在图5A中的if语句的情况那样使用布尔(真或假)选择来做出的。
再次,处理这种情况的方式仍然是将针对占用备选对象的控制条件转换成布尔形式,并且寻找针对该条件的值的一位或全位布尔表示。对于多路条件的给定执行而言,这些条件中最多只有一个条件能够为真。然而,与占用所有备选对象的情形不同,这些备选对象中的一些是未占用的,这意味着在选择这种备选对象的情况下,将具有在执行U中或在执行U之前计算出的值,而不是具有通过占用备选对象代码选择中的一个计算出的值。
为了处理这种情形,创建了一个追补条件,当占用备选对象的条件全部为假时,该追补条件正好为真。当该条件为真时,保留从U引入的计算结果(或者是在U中计算出的或者是在U之前计算出的)。
由于在包括这个追补条件在内的上述条件中正好只有一个为真,而所有其余的都为假。因此保留与原始程序中备选对象的选择相对应的结果,而取消那些与在原始程序中将不会被求值的那些。结果是这样的,即,当如此处所描述的那样执行了被合并的多路选择后到达了Z时,不管选择对应于多路选择中占用的备选对象还是未占用的备选对象,从Z所看到的值的状态完全如同已经执行了原始计算一样。
2.10.6.分布式联锁和分段式联锁。在一些情况下,预传递计算可执行消耗大量计算时间或计算空间的计算,而希望将这些工作可分布到网络中的多个计算机中。在该情形中,可以在服务器上执行预传递计算,其中由客户端上的预产生计算将工作封装并发送给服务器,由与执行预消耗计算的客户端相同或不同的客户端接收预传递计算结果并解封装。
在该情况下,能够创建联锁以将预产生计算转换成封装有用于服务器传递计算的工作的产生计算,其中在相同的客户端或不同的客户端上通过消耗计算对结果进行接收、解封装、以及解释。几乎以正常的方式来构建联锁,但是产生客户端将包含了很多值的缓冲发送到传递服务器,而传递服务器将包含了很多值的缓冲发送到消耗客户端。即,通过在一般的、单站点形式的联锁中作为处理的部分状态而被发送的那些,取而代之地被采用为占用缓冲的产生状态的相关部分的像,之后由传递服务器接收该缓冲,传递服务器使用该缓冲作为部分开始传递状态的像,执行其传递计算,将最终传递状态的相关部分的像放在缓冲中,之后该缓冲被发送到消耗客户端,由消耗客户端将在缓冲中的像解释为部分初始消耗状态。
这种从产生客户端到传递服务器到消耗客户端(有可能在网络中与产生客户端相同的计算机上)的联锁是分布式联锁。
联锁的传递部分是具有图1中示出的关系结构的联锁段。类似地,这种分布式联锁的产生部分和消耗部分是多个联锁段。
存在着其中分布可能是有用的其它情形。例如,可以是这样的情形,即,不存在预传递计算,并且所有的活动都是在计算的预产生部分和预消耗部分中。一个示例是在网络中的计算机上执行消息机制的发送部分和接收部分的代码,其中对于任何给定的消息,一台计算机进行发送而另一台计算机进行接收。为了保护这种消息机制,利用空的预传递计算(恒等式函数(identity function),不做出任何数据改变),将发送方(预产生)计算及接收方(预消耗)联锁起来。通过对它们进行编码来保护消息并确保对发送或接收机制进行的篡改将几乎肯定失败,这是由于以这种方式进行篡改将挫败攻击者对于这种篡改的结果所具有的鬼祟希望。这种联锁在通信的两端安装了秘密的且防篡改的内置认证机制,对于攻击者来说,通过消息欺骗(message spoofing)、或通过重放(具有适当的消息内容)或其它基于通信的攻击来破坏该机制会非常困难,并且由于应用了对于安装这种联锁的处理来说是固有的变换,因此该机制同时通过以编码形式发送消息内容来保护消息内容。
使多个段之间的像消息防篡改。当计算的多个段是分布式联锁的一部分时,拥有这些段的网络节点之间的通信一般地暴露在网络上(例如,在以太网上或在本地无线网络上)。因此,对在多个段之间传递的数据像提供有效的保护是非常重要的。
除了一般应用于非分布式计算的保护以外或者代替一般应用于非分布式计算的保护,优选地通过根据[16]并且具有在§2.7.2中所教导的对其的改进将这些段间数据像消息编码为存储阵列来保护它们,使得存储阵列的像从发送方被发送到接收方,发送方以海量数据编码格式准备数据,而接收方以海量数据编码格式来使用数据。如果存储像是阵列,可以另选地使用具有在本文§2.8.1这里所公开的改进的[9]的阵列保护,或者,如果访问阵列的代码是富循环的(明示或隐含的),可以采用[27]的阵列保护。
除了以上海量数据编码的通信以外,或者代替以上海量数据编码的通信,使用根据[17、18]的、具有在§2.7.5中所教导的改进的白盒密码法,发送方可以对发送的数据的像(海量数据编码的或其它的)进行加密并且由接收方来解密,这为多个分布式段之间的数据像的发送提供了密码级的保护。
以上的海量数据编码保护和加密保护都具有所期望的防篡改特性,而不仅仅是模糊性,因为对海量数据编码的数据、或访问这些数据的代码、或加密后的数据、或白盒加密或解密的代码所做的任何修改都会有很大的几率产生混乱而不是有目的的结果,因而挫败了攻击者可以对于这种篡改所具有的任何目的。
2.10.7.确保动态随机性。在§2.9.1标题为情况1:不存在或弱X→Y数据依赖性的部分描述了这样一种方法,通过该方法在联锁中可以通过把在X中产生的值作为系数来对Y中的数据值进行编码,能够提高Y对在X中产生的结果的数据依赖性。
假设希望使Y的性态以明显随机的、不可重复的方式发生改变,使得通过在Y处的计算中的明显地混乱的变化来损害攻击者反复地观察由Y传递的性态的能力。
选择作为熵源的X BB集合,这或者是由于X BB集合能够访问程序的输入,而根据该输入能够计算强散列(可能密码地强),使得输入中的各个小变化都会对散列进行剧烈地修改,或者是由于X BB集合读取了一个或更多个有效的随机源,诸如高速硬件实时时钟的低阶位、或使用不稳定电子处理以产生‘噪声’并将其转换成(真正的)随机比特流的随机产生装置。
之后,将X联锁到Y,使得Y′(最终修改后的Y)取决于在X中产生的值(包括那些取决于它们的熵源的值),并且使用在情况1:不存在或弱X→Y数据依赖性这一部分中公开的用于创建数据依赖性的方法,创建从X′到Y′的数据依赖性,使得Y′的执行根据在X′中获得的熵随机地变化。
由于在§2.10.1中公开的方法,如果希望的话,这可以与程序中的任何其它联锁相当独立地进行;即,只要需要,就可以向程序的任何部分的执行添加动态随机性,而与程序中出现的任何其它联锁无关。
2.10.8.确保变量依赖性。使用在§2.10.7中给出的并且具有下述修改的方法,可以确保变量依赖性(在消耗BB集合的计算中的数据对产生BB中的变量的值的依赖性),所述修改为:X BB集合不必是熵源因而来自XBB集合的值都不需要携带熵。
2.10.9.与硬件组件的联锁。在上面名为软件实体和组件以及作为软件的电路的部分中,注意到由于可以将电路表达为以诸如VHDL的电路描述编程语言编写的程序,因此电路可以是软件实体。
接下来,在包括一个或更多个具有VHDL或一些类似编程语言的高级描述的硬件电路的预产生BB集合与也包括一个或更多个具有VHDL或类VHDL语言的高级描述的硬件电路的预消耗BB集合之间,可以安装联锁。
通过像在普通编程语言中修改预产生集合的描述那样修改预产生集合的VHDL描述或类VHDL描述,由此修改根据VHDL描述或类VHDL描述而创建的相应电路,安装联锁将会把预产生集合改变为产生集合。
类似地,通过像在普通编程语言中修改预消耗集合的描述那样修改预消耗集合的VHDL描述或类VHDL描述,由此修改根据VHDL描述或类VHDL描述而创建的相应电路,安装联锁将会把预消耗集合改变为消耗集合。
沿着相似的线路,可以将电路一个或多个电路(作为预产生BB集合)联锁到软件或固件代码(作为预消耗BB集合),或者将软件或固件代码(作为预产生BB集合)联锁到一个或多个电路(作为预消耗BB集合)。另外,预传递软件可以是、或可以包括可以用VHDL语言或类VHDL语言来描述的一个或多个电路。
在各情况中,联锁处理通过凭借对硬件电路的VHDL语言或类VHDL语言的描述软件进行的修改来修改硬件电路,从而影响硬件电路。具体地,将包括预产生BB集合的一个或多个电路变换成具有其原始功能的经编码的输出扩展(OE);将包括预传递BB集合的一个或多个电路变换成其原始功能的经编码的间插聚合(IA),该经编码的间插聚合具有将扩展信息从其输入传递到其输出的一些双射;而包括预消耗BB集合的一个或多个电路变换成具有其原始功能的经编码的反向部分求值(RPE)。
2.11.联锁以满足特定需要的示例性应用。现在将注意力转移到将以上的教导应用于联锁的具体应用上来,该联锁保证了在sbe中的特定性态,或者满足特定的安全性要求。
2.11.1.历史依赖性。假设从BB x1,...,xm仅经由分支到达程序中的BBy1,...,yn。攻击者可能修改程序,使得一些其它的BB(例如,与x1,...,xm相异的w1,...,wk)能够分支到y1,...,yn中的一些或全部。将这种攻击者增加的分支称为外来分支(foreign branch)。
如果希望确保到y
1,...,y
n的外来分支不能成功,则选择X={x
1,...,x
m}作为预产生BB集合,选择Y={y
1,...,y
n}作为预消耗BB集合,并且选择
(空集)作为预传递BB集合,并且安装根据本申请的一般方法从X到Y的联锁。
结果,外来分支将导致混乱的性态或失败。
因此,安装这种联锁使得执行是依赖于历史的:受影响的软件拒绝正常执行,除非在其执行历史记录中,X的元素的执行直接在Y中元素的执行之前。
2.11.2.通过校验和的完整性验证。防止软件篡改的普通技术是代码校验和的一些变型:将代码作为数据来处理,而将代码的多个部分作为整数型字(或字节)的阵列来处理,利用单一校验和或组合校验和、或者利用单一校验和与组合校验和二者来计算阵列的校验和。这可以这样做:最初验证载入的像与装配文件中的哪些相匹配,或者随后以周期性的间隔验证程序的代码没有受到篡改的修改。
这种校验和的最安全的类型是使用密码地强散列来计算的:具有该特性的散列函数,即,给定针对校验和的值,很难发现使得校验和具有该值的整数阵列、或对整数阵列的修改。用于计算这种校验和的算法的例子是MD5[13]和SHA-1[14]。
不幸地是,这种对软件修改的防御受到两个非常严重的弱点的困扰。
(1)如果攻击者能够修改代码使得校验和的失配不触发失败,则攻击者能够在不会由于校验和的失配而触发失败的情况下修改代码。即,攻击者可以简单地执行通过小的改变,如‘干扰’有关失败条件所采取的分支(即,以无条件分支来替换该有条件分支)来破坏失配的结果,使得不管校验和是否匹配,失败分支都不会出现,而不是试图解决在保留校验和的同时如何修改代码的潜在难题。
通过这样一个事实,即,不管是低安全性的简单校验和算法还是诸如MD5[13]和SHA-1[14]的更安全的校验和算法都是公知的并因此是可识别的,有助于攻击者定位这种校验和验证代码以及因此定位分支‘干扰’将阻止失败响应的代码位置。
(2)当在现代操作系统上执行现代软件时,对于要被修改的程序来说,一旦被载入则不同寻常的是:程序通常利用驻留在其访问控制位被操作系统设定为只读状态的存储器中的代码的单一、静态主体来执行其全部工作。
这种代码稳定性使得在[29]中描述的攻击形式成为可能。在这种攻击中,简单地复制了软件像。很多现代处理器区分数据访问和代码访问。(在某种程度上,可以允许在没有增加指令中地址字段长度的情况下提高寻址能力,因为取决于是作为数据取回/存储的(即数据访问)还是作为指令取回的(即执行访问(execute access)),可以允许同一地址指向不同的位置)。副本中的一份是攻击者篡改了的修改代码,而另一份是由软件出于校验和目的而访问的原始代码。由于这样的事实,即,未执行的原始代码(没有被修改)不可能保护攻击者可随意篡改的修改代码(已执行的),因此软件作者的由软件进行的软件自我校验和应该防止篡改的意图完全失败。
这种攻击具有令人惊讶的低开销并且对于操作系统专家来说非常容易执行。
通过在§2.10.4中给出的方法能够解决以上所注意到的第一个弱点。预产生BB集合(一般仅仅是一个BB)计算并检查校验和;对校验和的检查控制了到校验和成功目的地或校验和失败目的地的条件分支;在条件分支的目的地处的BB集合(一般各仅仅是一个BB)是预消耗BB,而条件是校验和匹配或匹配失败。如果攻击者修改了校验和检查代码(例如,通过干扰分支),安装了这种依赖于条件的联锁会使执行失败。
以上所注意到的第二个弱点更加难以管理。近来市售的操作系统的发布使得修改程序中的代码越来越困难。在这种趋势下,执行[29]中所描述的代码-像类型攻击的攻击者一般地具有在完全控制下的计算机,该计算机运行在攻击者控制下的操作系统。例如,使用诸如Linux、Hurd、或Open-BSD的开放源代码的操作系统,这将肯定是可行的。
一种方法是将要保护的程序划分为多个区域。当前区域(程序计数器所指的区域)中的代码必须是可执行的,而其它区域中的代码不需要是可执行的。可以利用这一事实在区域到区域的转移之前修改程序的像。刚好在控制从区域M转移到区域N之前,区域M的出口代码把M的代码修改成不可执行状态(除了出口代码自身以外)并且将N的代码修改成可执行状态。如果他们处在关键位置(例如,如果他们形成了联锁的预产生BB集合中的部分代码,从而任何小的改变都将导致失败),则这种修改不需要很大:这里几个字节那里几个字节就非常足够了。程序代码在每个区域具有至少一种状态,其中该区域是可执行的而其它区域是不可执行的,并且因此每个状态具有至少一个校验和并且因此每个区域具有至少一个校验和。在给定区域中执行的校验和代码使用适于该区域的校验和。
这禁止了上述的攻击活动,因为在代码中执行的改变必须在实际执行了的代码像上执行:如果不是这样,则转移进新的区域会进入处于不可执行状态的代码,并且执行将失败,从而防止了攻击者的任何进一步进展。
一种改进的地方是采用了多个不可执行状态并且在这些多个不可执行状态中进行随机选择(例如,通过使用实时时钟或进程标识符等的低阶位来从它们中进行选择)或伪随机选择(例如,通过采用来自程序的输入的熵来产生散列并且之后采用该散列的低阶位来从它们中进行选择)。这增大了攻击者在试图确定如何战胜这种保护中的困难。
然而,由于在区域转移期间执行代码状态改变的代码将使用特殊的指令或系统调用以实现改变,因此它可能很明显。为了防止移除保护,最后的步骤是将执行状态改变的计算与那些执行接下来的校验和检查的计算联锁起来,并且在这种代码状态改变和检查之间执行联锁链接。然后,对代码状态改变或代码状态检查的修改都将有很大的几率造成混乱的性态,因而挫败攻击者可能对改变代码性态所具有的任何特定目的。
2.11.3.在复杂的数据结构中隐藏信息。假设希望向攻击者隐藏秘密的数据(信息片)。回顾之前讨论的用于隐藏数据的方法,并且然后公开一种处理不论小或者大的静态和动态常量(动态常量是在运行时计算出的并且在计算出之后不改变)以及不论小或者大的非常量数据片的另选的、强力的方法。
之前公开的数据隐藏方法。如果数据相对较小并且是静态或动态常量,可以使用在§2.6中教导的方法、或[2、4、5、19、20]的方法或在§2.7和§2.8这里所公开的[2、4、5、19、20]的方法的扩展;或者,根据在§2.5.3中所公开的或引用的恒等式、或在§2.5.4中所公开的恒等式、或由§2.5.1或§2.5.2中所公开的方法发现的恒等式,可以替换使用了该数据的表达式以及在那些使用附近的表达式。
如果数据是大的且静态或动态常量,则可以使用§2.6中的方法,其中以多个段来产生大的常量,每段可以作为独立的小常量处理。
如果数据不是必须是常量,并且数据小,则可以通过采用[2、4、5、9、19、20]的方法或者在§2.7和§2.8中列出的[2、4、5、9、19、20]的方法的扩展来隐藏它;或者,根据在§2.5.3中所公开的或引用的恒等式、或在§2.5.4中所公开的恒等式、或由§2.5.1或§2.5.2中所公开的方法发现的恒等式,可以替换使用了该值的表达式以及在那些使用附近的表达式。
如果数据不是必须是常量,并且数据大,则可以使用如在前一段中相同但应用于作为整个值的“段”的小的值的方法。或者,可以采用[16]的方法,后者在§2.7.2中公开的它的扩展,或者,如果数据采用了阵列的形式,则可以使用具有在§2.8.1这里所公开的改进的[9]的阵列保护,或者如果数据是阵列并且访问它的代码是富循环的(明示或隐含的),则可以使用[27]的方法来保护。
复杂数据结构方法。存在一种强有力的备选方法,该备选方法可以隐藏不管大还是小的静态或动态常量数据和不管大或小的动态变化数据(变量或特定的变量集合)。
考虑复杂的数据结构,该结构包含一系列数据段,其中各数据段包含下述的一些组合:标量变量、标量变量的阵列、到其它这种数据段的指针、以及到其它这种数据段的指针阵列的,其中数据段链接在一起使得对于作为节点的各段以及作定义弧的指针而言,该结构是有向图,多数节点具有大于1的出度,大多数节点具有大于1的入度,并且对于大多数的节点对来说,存在着从一个节点到另一个节点的多于一条的路径。选择这些节点(数据段)中的一个作为正规开始节点。
可以用C或C++编程语言或它们的同类语言将这种数据结构实现为一系列结构(即,每个都是用C或C++实现的结构),包括标量变量、标量变量的阵列、指针变量、以及指针变量的阵列,其中,在程序启动时或在如上所述在将指针用于隐藏一些尺寸的数据之前在随后的时间点对指针进行初始化。或者,使用C中malloc()函数或其同类函数中的一个或使用C++中的new操作符,可以动态地分配该结构。最后,不管是否声明为阵列或使用C中malloc()或calloc()或使用C++中的new[]操作符来分配,可以采用结构变量(struct variable)的阵列,并且以阵列索引(将所有数据段限制至相同的内布局)来代替指针变量,或者可以将阵列方法与以上的多链接、基于指针的形式结合起来。
无论以上的多链接的(无论是通过指针还是通过索引或通过二者)数据结构是静态分配的、或是在例程主体中声明的、或是使用C中的malloc()或使用C++中的new和/或new[]动态地分配的,都将这种多链接的数据结构称为储存库,其中,储存库中的各标量变量都存储标量值。
然后,使用两种方法将信息隐藏在储存库中,这两种方法都是基于§2.6的数据隐藏方法。第一种方法确定如何对作为正在隐藏的数据或者数据的元素的特定数据片进行寻址。第二种方法确定如何存储数据中的特定片(即,它是如何编码的)。
储存库中的路径包括值序列,其中,这些值表示出一系列标量存取或指针存取。例如,可以分配数字1,...,64以指代结构中的第一到第64个标量数据字段(或阵列中的元素),65,...,128以指代第一到第64个指针字段(或阵列中的元素),分配129,...,192以指代第一到第64个标量阵列字段,分配193,...,255以指代第一到第63个指针阵列字段,而分配0以表示该路径的结束。可以将所有的这些值存储在(不带符号的)八位字节中。因此,可以使用以0字节结束的一串字节(如在C中一般表示的串那样)来表示从根数据结构开始的路径。
例如,假设为了找到特定的标量值,在根结构开始,接着是第三指针字段中指向另一结构的指针,选择第二指针阵列,索引出阵列中的第9指针,跟随那个指针到另一结构,并且之后选择第8标量数据字段。之后,用字节向量(67,194,73,8,0)表示该路径。
可以有很多其它形式的路径编码,这对于熟悉编译器器构造以及针对诸如C或C++的被编译语言的各种的数据结构访问的实现的领域中的技术人员来说将是明显的。而且,对于熟悉编译器构造领域的技术人员来说,用于解释这种经编码的路径以访问该路径的目标值的代码构造同样简单。
这种路径非常地适用于根据§2.6的常量隐藏方法的隐藏。而且,§2.6还公开了确保常量路径是动态常量(见以上标题为添加动态随机性的部分)的方法;即,在程序启动时,或在储存库启动时(如果储存库是临时的),恰恰路径将应用于存储在储存库中的特定标量,则该路径是不可测的;如果该储存库是临时的,其路径在程序运行之间、以及在程序运行内的储存库的实例化之间将发生变化。
一般地,路径在标量或标量阵列结束。由于指针一定是处于未编码形式以供使用,所以这种即时复杂数据结构方法在隐藏指针方面不是非常有帮助。然而,使用[2、4、5、9、20]的数据编码方法或在§2.7和§2.8这里公开的[2、4、5、9、20]的数据编码方法的扩展,通过对值以及使用这些值的代码进行编码,可以采用经编码的值而无需将它们解码,因此即时复杂数据结构方法非常适用于标量数据的保护。
如果根据[16]的方法和系统或在§2.7.2中教导的[16]的方法和系统的扩展,将链接的数据结构存储在编码的软件存储器阵列中,则可以保护指针以及值。根据[16]或其扩展的指针都是经编码的整数值,取回和存储经编码的整数值都无需立即解码,因此,被作为特殊值而处理的指针得到完全保护。另外,由于编码的软件存储器阵列本身提供了实质性保护,因此[16]的保护或在§2.7.2中教导的[16]的保护的扩展使得可以减少在软件存储器阵列中存储的隐藏存储结构的复杂性。
或者,如果存取数据结构的代码是富循环的(明示的或隐含的),可以如[27]中所教导地将指针表示索引的模糊且时变的向量,由此将它们隐藏。
为了在存储、或取回、或取回并在计算中直接使用标量数据时保护该标量数据,以经编码的形式来存储数据并使用上述的数据和计算编码方法来隐藏存储的值、取回的值、或取回并在计算中直接使用的值,如在[2、4、5、9、19、20]中所公开的或在§2.7和§2.8中这里所公开的这些的扩展中所公开的。
这些上述的方法采用(静态或动态)常量系数以在一族编码的不同成员之间进行区分。例如,使用[20]的编码,以其两个系数:其应该是奇的缩放比例以及其不受限制的偏差(bias)来确定任何特定编码。
再次,可以通过所有编码的系数来表示储存库中的所有标量位置的所有编码。还可以进一步进行步骤并使用另外的常量值来标识特定系数所属的编码族。如果不采用该进一步的步骤,则以具体的编码族来标识各储存库数据,并且只需要其系数来消除它的歧义。
使用§2.6的方法来隐藏系数的常量向量、或族标识符和系数的常量向量。这些常量既可以是静态的,也可以是使用在标题为添加动态随机性的部分中的§2.6中给出的并在§2.10.7中详细描述的方法动态地产生的;使用在§2.10.8中教导的方法,根据来自其它部分或程序的数据来产生它们的表示。动态地随机或取决于变量的表示引起更大的开销,但提供了更多安全性,因此在资源因素允许的情况下推荐使用动态地随机或取决于变量的表示。
使用§2.2.10.7或§2.10.8中的方法中的一个或二个来将这种数据隐藏方法转换成联锁,在可行的情况下,出于安全性原因推荐使用这。
2.11.4.将应用绑定到共享库。当从各种目标代码文件将应用链接在一起的时候,经常会引入用于库例程的代码,该库例程执行很多不同应用所共有的功能。
在库代码内(所有组件都处于库代码自身之内)进行联锁只是普通的联锁。然而,当一些联锁组件处于库内而其它组件在库代码随后将要链接到的应用中时,存在变型。
可能是这样的,即,通过链接到库代码而获得的功能要求经由联锁的性态保护,例如,为了确保调用正确的库例程,而不是忽略它的调用或将其调用转移到一些其它例程,或者确保从库例程退出时,将控制返回到跟随在期待的调用位置处的调用之后的代码,而不是将其转移到其它地方。
困难是,为了安装联锁,不能修改在可由给定平台上的多个进程使用的固定的且通常可同时共享的代码片中的库代码(诸如,动态存取*共享对象(用于UnixTM或Linux平台的a.so(共享对象)文件;用于WindowsTM平台的a.dll(动态连接库)文件)。[*例如,在WindowsTM平台上,有时通过调用LoadLibrary(...)可以将给定的库例程组映射到应用的地址空间中,可以使用GetProcAddress(...)来访问其中的例程,并且在该应用以例程组结束之后,可以通过调用FreeLibrary(...)从地址空间中移除该组]。
从库代码联锁到调用方代码。从库代码中的BB的集合X联锁到使用库代码的应用中的BB的变量集合Y是简单的:以一般方式将预产生代码转换成计算完整的OE的产生代码,设IA为恒等式IA(无修改或传递代码要求),并且以一般方式把从库接收信息的预消耗代码修改成消耗RPE。以一般方式应用编码以形成X′和Y′。唯一的不同是,必须保存关于X的OE与X′的编码的信息以使得在针对使用库代码的各调用应用来准备用于Y的RPE和Y′的编码的代码。
从调用方代码联锁到库代码。由于在没有调用应用的详情知识的情况下预先创建了库代码,因此这是联锁的反向形式,即,从使用库代码的应用中的预产生BB的集合X联锁到在出现问题的被调用库代码中的预消耗BB的集合Y。
当产生了用于库例程的代码时,无法知道进行调用的上下文的细节。然而,所知道的是,传递到库例程的API的变元的细节不是变元值的细节,而是它们的类型、它们的格式、以及它们作为库被调用方的合法变元所必须遵守的任何约束。因此,装配有关于各可能调用上下文信息的特定片:专门与变元传递的上述方面有关的那些。
因此处于这样的位置,即,在建立到库被调用方中的Y预消耗BB集合的联锁之前,象征性地产生用于泛型调用方(如,在泛型预产生方BB集合X中的代码)。
之后将泛型调用方BB集合X联锁到实际的库被调用方BB集合Y,创造X的OE和Y的RPE,并且将这些编码入X′和Y″并且建立从泛型调用方到实际的库被调用方的联锁。如以上从库代码到调用方代码的联锁那样,使IA为恒等式IA(无修改或传递代码要求)。
之后为了从执行调用的实际调用方的BB集合X联锁到库BB集合Y(其中,库实际地包含用于编码的后联锁BB集合Y′的代码),简单地按照X的OE来排列BB集合X的OE,由于X仅包含所有调用方都共有的泛型代码,因此这总是可能的,并且完全如对X′编码那样将X及其OE编码为X′,再次,由于只涉及了所有调用方都共有的泛型代码,因此这总是可能的。
作为上述方法的结果,由于少量的简单变元可能存在从调用方到被调用库代码的不充分依赖性。在该情况下,解决方案是,在建立以上的泛型联锁之前,增加更多的变元和/或使变元更加复杂,由此创造这样的情形,即,不管在该情况下的联锁代码的泛型特性如何,从调用方对库被调用方的依赖性将足够创造安全的联锁。
因此,将功能分在多个可共享库中对于联锁来说没有障碍,即使当联锁必须跨越库边界,不管是否是动态的,以及不管是从库被调用方到调用方还是从调用方到库被调用方。
本发明的实施方式可以任何常规计算机编程语言来实现。例如,优选实施方式能够以过程式编程语言(例如,“C”)或在面向对象语言(例如,“C++”)来实现。可以将本发明的另选实施方式实现为预编程的硬件元件、其它相关的组件、或实现为硬件和软件组件的组合。
可以将实施方式实现为由计算机系统使用的计算机程序产品。这种实现可包括固定在诸如计算机可读介质(例如,软盘、CD-ROM、ROM、或固定磁盘)的有形介质上的一系列的计算机指令或可经由调制解调器或其它接口设备(例如,通过介质连接到网络的通信适配器)而可传输到计算机系统的一系列的计算机指令。介质既可以是有形介质(例如,光或电通信线路)或以无线技术(例如,微波、红外线或其它传输技术)而实现的介质。一系列的计算机指令实施了本文之前所描述的全部功能或部分功能。本领域的技术人员应该理解,这些计算机指令可以以很多计算机架构或操作系统所使用的多种编程语言来编写。另外,可以将这种指令存储在任意的存储设备中,诸如半导体存储器设备、磁存储器设备、光存储器设备或其它存储器设备,而且可以使用任意的通信技术(诸如光传输技术、红外传输技术、微波传输技术、或其它传输技术)来传输这种指令。令人期待的是,可以将这种计算机程序产品发布为具有打印或电子文档(例如,拆封许可软件)的可移除介质、用计算机系统来预先载入(例如,在系统ROM上或固定磁盘上)的可移除介质,或者在网络上(例如,互联网或万维网)从服务器发布的可移除介质。当然,可以将本发明的一些实施方式实现为软件(例如,计算机程序产品)与硬件的结合。可以完全以硬件或完全以软件(例如,计算机程序产品)来实现本发明的其它实施方式。
理解本发明的人现在可以想到以上实施方式的另选结构和实施方式或变型,所有这些都落入在所附权利要求书所限定的本发明的范围中。