王志宇,席剑霄,张 莹,郑江东,罗 迎
(1.公安部第一研究所,北京 100048;2.北京握奇数据股份有限公司,北京 100102)
集成电路芯片的安全等级能力是对芯片进行评估的重要维度,安全芯片须通过高标准认证以符合商用密码产品对芯片安全能力的要求。由于成本和应用场景等原因,能够达到此类安全认证级别的集成电路芯片基本都属于硬件资源受限的芯片[1-2]。资源受限安全芯片(以下简称“安全芯片”)操作系统作为安全芯片的运行支撑平台,发展至今形成了开放式(Open)架构和封闭式(Closed)架构2 种技术路线。其中,开放式架构实现了用户程序和操作系统的分离,降低了应用程序的编写、编译、下载、执行与芯片操作系统的耦合性。但是,开放式架构也存在如下劣势。
(1)现有主流开放式架构主要采用国外厂商专利技术,需要缴纳专利费用,国内厂商目前还缺少自主可控的技术主导力。
(2)开放式架构主要采用栈帧结构,在方法调用过程中涉及入栈和出栈,在字节码执行过程中也涉及操作数栈的入栈和出栈,解释执行效率较低。
(3)栈帧结构易导致内存泄露,存在安全隐患。
(4)指令集源于通用指令集,与行业应用结合度不高,精简度不够。
针对上述原因,本文提出了一种安全芯片开放式运行环境设计方案,通过对现有主流运行环境重新进行设计,并结合行业安全应用需求扩展指令集,使运行环境中的执行效率、应用开发便捷、安全性等方面得到提升,具有较好的应用前景。
安全芯片内部嵌入式操作系统架构如图1所示。
嵌入式操作系统分为3 层,即应用层、安全运行环境和硬件驱动层。其中,安全运行环境是一个运行在硬件驱动层和应用层之间的中间平台层,安全运行环境与硬件驱动层分离,便于安全运行环境在不同芯片硬件平台之间移植切换;安全运行环境提供一系列应用程序接口(Application Programming Interface,API)给应用层,供应用开发者开发各种行业应用,这些应用在产品发行后也可以下载到安全运行环境进行加载、运行。安全运行环境负责对芯片中的应用进行管理,保护应用本身以及应用相关数据信息的安全。
本文提出的面向资源受限安全芯片的开放式运行环境包括芯片外部的上位机编译器和芯片内部的虚拟机解释器2 个部分,总体架构如图2所示。在总体架构中,芯片外部的上位机编译器将源文件编译转换成可执行二进制文件,芯片内部的虚拟机解释器加载并解释执行该可执行二进制文件。架构中各模块定义如下:(1)源文件是指基于通用语言规范限定编写的源代码;(2)编译转换是指将源代码编译为中间指令集;(3)可执行二进制文件是指包含方法组件的特定格式文件;(4)解释执行是指加载可执行二进制文件中的字节码,在虚拟机中解释执行。
资源受限安全芯片因Flash 空间和随机存取存储器(Random Access Memory,RAM)空间受限,只能运行基于16 位操作指令的虚拟机,不能基于通用语言规范来编写应用源代码,因此,需要对通用语言规范做以下限定。
(1)数据类型支持限定。支持布尔类型(boolean)和数值类型,数值类型包括字节型(byte)、短整型(short)及整型(int)等,不支持字符型(char)、长整型(long)和浮点型。
(2)操作指令限定。在虚拟机中运行的基本数据单元为16 位数据,boolean 类型、byte 类型、short 类型及引用类型的存储参数、局部变量和中间运算结果占用1 个基本数据单元,int类型的存储参数、局部变量和中间运算结果占用2 个基本数据单元,boolean 和byte 类型的数值在算术运算时先将数值类型提升为short 类型,若其中一个操作数类型为int 类型,则再将数值类型提升为int 类型。
(3)数值类型提升限定。应用于算术运算符的操作数包括一元数值类型提升和二元数值类型提升,比如:当操作数在编译时的类型为byte,则须通过宽化类型转换方法将其转换为short 类型;若其中一个操作数类型为int 类型,另一个操作数类型也转换为int 类型。
(4)数组创建和访问限定。数组类型和索引为short 类型,只支持一维数组。
(5)关键字限定。不支持复杂关键字,例如,线程同步synchronized、枚举enum、断言assert 等。
编译转换过程如图3所示。
编译器将源文件编译转换为可执行二进制文件,转换过程包括词法分析、语法分析、语义分析以及代码生成4 个阶段。其中,词法分析阶段是将源代码转换为索引流;语法分析阶段是将词法分析后形成的索引流中的索引组合成符合语法规范的语法节点,形成一棵基本的抽象语法树(Abstract Syntax Tree,AST);语义分析阶段依据语言规范对AST 进行严格语法检查,还需要为后续的代码生成阶段准备各种数据;代码生成阶段将AST 转换为字节码。
中间指令集是代码生成阶段中的一种中间指令,中间指令集格式经各种技术优化后,可生成最终的优化指令码。部分中间指令集如表1所示。
表1 中间指令集
针对通用语言规范限定要求,编译器在处理字面量时需按照值大小确定类型,例如,在short 类型表示范围内,则按short 类型处理,在超出short 类型表示范围时,则按int 类型处理;编译器在处理操作符表达式时须做类型提升,运算符对应的表达式类型是其操作数提升后的类型,只能是short 类型或int 类型;编译器在生成栈和局部变量操作、类型转换、操作符表达式、方法调动返回等中间指令集的过程中,boolean类型、byte 类型、short 类型及引用类型的局部变量编译后占用1 个索引位置,int 类型编译后则占用2 个索引位置。
中间指令集通过压缩转换,生成目标指令并以可执行二进制文件的格式存储。可执行二进制文件中的常量池组件,将每种引用类型放在一起形成一个子常量池,具体包括:(1)将所有的类引用类型放在一起形成类子常量池;(2)将所有的静态方法引用类型放在一起形成静态方法子常量池;(3)将所有的虚方法引用类型放在一起形成虚方法子常量池;(4)将所有的super 方法引用类型放在一起形成super 方法子常量池;(5)将所有的静态域引用类型放在一起形成静态域子常量池;(6)将所有的实例域引用类型放在一起形成实例域子常量池。
通过上述过程,常量池形成6 个子常量池,包括:(1)类引用;(2)静态方法引用;(3)虚方法引用;(4)super 方法引用;(5)静态域引用;(6)实例域引用。
芯片内部的虚拟机解释器解释执行可执行二进制文件中的指令集,指令集的解释执行过程如图4所示。
指令由一个字节长度的操作码组成,操作码指定要执行的操作,并由零个或多个操作数表示要操作的值。与基于栈帧的指令集相比,本文所设计的基于寄存器的指令集在指令执行性能上更优,同时,结合行业应用需求,将应用实现过程中使用频率较高的基础API 封装成宏指令,通过隐含参数信息、定义多种操作格式、单字节常量索引、宏指令等方法精简设计后形成6 类指令。
一是隐含参数信息指令。如表2所示,将操作数和寄存器编号都隐含到操作码的常量赋值指令中。
表2 常量赋值指令
二是具有多种操作格式的高频指令。如表3所示为常用算术加操作指令。
表3 加操作指令
三是基于不同参数个数、具有不同指令格式的指令。如表4所示为静态方法调用指令。
表4 静态方法调用指令
四是常用数据类型指令和不常用数据类型指令。例如,short 数据类型指令和int 数据类型指令。
五是具有单字节常量池索引的指令。如表5所示为静态域访问指令。
表5 静态域访问指令
六是宏指令。如表6所示为数组拷贝宏指令。
表6 数组拷贝宏指令
指令集解释执行时采用了寄存器结构,甚至宏指令,在字节码执行过程中不涉及操作数栈的入栈和出栈,与栈帧结构相比,解释执行的效率较高。通过对比Java 智能卡(JavaCard)的实现来分析性能,部分字节码指令性能的比对结果如表7所示。
表7 部分字节码指令性能比对
如表8所示,以参考代码“short totalLen=(short)(len+recLen);”的加操作指令为例,通过字节码、操作数栈和计算过程的比对,进一步分析性能。
表8 加操作指令性能比对
如表9所示,以交通电子存折和电子钱包应用(Electronic Deposit & Electronic Purse,EDEP)的交易过程为例,从应用层面进一步分析本文设计指令集的性能。
表9 EDEP 应用性能比对
虚拟机运行在安全芯片中,针对物理层的攻击与防护更多依赖于芯片本身,而对虚拟机本身的攻击与防护更多是依靠逻辑层实现[3]。针对虚拟机逻辑层的常用攻击手段是通过修改字节码,使得应用运行过程中发生内存泄露,从而非法获取芯片内部机密数据和其他应用数据[4]。本文所设计的安全芯片开放式运行环境具备较好的字节码指令集安全能力。以JavaCard 的栈帧访问为例来分析本文设计的字节码指令集的安全性。针对JavaCard 栈帧的常用攻击手段是替换或删除某些字节码,打乱栈帧结构,使得栈帧溢出导致内存泄露[5]。本文以删除字节码的方式作为示例,进行了详细的安全对比分析。
以源代码“var=0;”为例,给局部变量var赋值0,对应JavaCard 的字节码如下所示:
sconst_0;
sstore_3;
sconst_0 的操作数栈过程如下所示:
… -> …, 0
将一个short 值0 压入栈中,将sconst_0 删掉之后,对于操作数栈来说,少了一次压栈操作,即少了将0 压入栈中的过程。
后续字节码是sstore_3,操作数栈过程如下所示:
…, value -> …
将栈顶的一个short 值弹出,并将该值赋给第3 个局部变量,结合sconst_0,在原来执行sstore_3 时,应将0 从栈顶弹出,赋给第3 个局部变量,完成var=0的过程。将sconst_0删掉之后,当继续执行sstore_3 时,从栈顶弹出某一个值,该值存在较大的不可控性,会影响本方法中的逻辑正确性,在极端的情况下,该值会从上一个栈帧中弹出,直接导致上一栈帧内存泄露。如果虚拟机栈帧不做安全防护就会存在极大的安全隐患。
本文设计的指令集,同样以源代码“var=0;”为例,对应字节码如下所示:
const-0/r3;
const-0/r3 的操作数栈过程如下所示:
…, r3 -> …, r3
将一个short 值0 赋值给寄存器r3 中。如果将const-0/r3 删掉之后,只是少了r3=0 的赋值过程,同样会影响本方法中的逻辑正确性,但不会直接导致上一栈帧内存泄露,安全性相对较高。
如表10 所示,列出了安全认证实验室测试报告中对开放式运行环境的安全检测项[6],以及本文提出的开放式运行环境的实际测试结果,依据中国银联股份有限公司发布的Q/CUP 040.2—2011《银联卡芯片安全规范 第2 部分:嵌入式软件规范》。
表10 安全检测项及测试结果
资源受限安全芯片中的开放式运行环境在技术上能支持多应用、产品发行后新应用的下载和应用远程管理,开放式运行环境中的多应用架构如图5所示。
由于同一个硬件平台上的应用可能来自不同的所有者,因此,在不同应用之间需要利用安全机制进行应用的隔离,以保护应用所有者的商业数据。
防火墙是应用运行时的强制保护,允许虚拟机在运行时自动进行额外的安全检查。应用通过防火墙隔离,形成单独的受保护空间环境,单个包中的所有应用共享同一个空间环境。应用中任何给定的数据和方法都有一个单独的受保护空间环境。
任何时刻,虚拟机内部只有一个受保护空间环境处于激活状态。当满足特定访问规则时,调用某些方法、从某些方法返回或异常退出时,虚拟机允许环境切换。在环境切换期间,之前的环境被推送到内部虚拟机栈上,新的环境成为当前激活环境,被调用的方法在新的环境中执行。从该方法退出后,虚拟机将执行环境恢复,恢复为切换之前的环境。
应用通过防火墙隔离,单个包中的所有应用共享同一个受保护空间环境,并允许同一个包内的应用相互进行数据访问。不同包之间的应用需满足特定规则(例如共享接口)才能跨过防火墙访问对方应用允许访问的数据和方法。
随着移动智能终端的普及,告别“一个应用一张卡”的多卡时代,一卡多用、多应用融合已成为新的发展趋势。在“一卡多用”产品发行过程中,由专门机构的管理者对基础、通用类型的信息进行统一管理,完成原始信息录入、确保信息真实性、维护变更信息等工作,是实现数据被多应用共享的最安全、经济的智能卡解决方案。
安全芯片产品广泛应用于数字身份、金融、电信、社保、交通、水电燃气、车载、密码钥匙等领域,提供身份识别、密钥生成、安全存储、数据保护等功能。本文设计的面向资源受限安全芯片的开放式安全运行环境的创新和提升体现为以下几点。
(1)支持更实用的指令集。精简指令集和应用向扩展指令集具有更高效的实用性,可广泛应用于智能卡、安全元件(Secure Element,SE)或安全微控制单元(Microcontroller Unit,MCU)等芯片。
(2)支持多应用融合。通过单芯片实现多个业务应用,改变了需要多颗芯片耦合实现业务功能的情况,大大降低了设备芯片成本和研发难度。
(3)支持内核化。可下沉到安全芯片作为内核(Kernel),各设备厂家和行业用户只需关注应用,便于产品快速落地和迭代。
(4)支持国产自主可控。具备打破国外厂商技术垄断的能力,可在安全芯片操作系统领域实现自主可控的目标。
安全芯片在商用密码产品中的使用非常广泛,在一些特定行业中,对于技术自主可控的需求是合理现实的,以前面对这类需求时,多是采用封闭架构(Closed)技术来实现的。这类技术难以支持业务功能变化快、多应用融合的使用场景,难以适应万物互联场景下的产品技术需求。本文设计的安全芯片运行环境,可以提供一个面向资源受限安全芯片的支持多应用和应用后下载的开放式架构解决方案。在保障数据安全的前提下,有效促进行业应用的发展。