@Intel SGX 读书笔记…
安装Intel SGX SDK后,你可以在[Intel SGX SDK Install Path]src下找到示例代码。
你可以在VS2017中打开示例项目:
SampleEnclave项目向您展示了如何从头开始编写enclave。本主题演示了enclave特性的以下基本方面:
注意:如果示例项目位于系统目录中,则需要管理员特权才能打开它。如果无法授予管理员权限,可以将项目文件夹复制到你的其他目录中。
配置并启用Intel SGX
一些OEM系统通过SW控制接口支持在BIOS中配置和启用Intel SGX。Intel SGX PSW公开了所有应用程序在创建应用程序之前都应该调用的API。API sgx_enable_device配置并启用Intel SGX设备(如果平台之前没有启用)。如果BIOS配置了Intel SGX作为调用的结果,那么BIOS配置需要重新启动才能生效(Intel SGX要在重新启动之后才能使用)。请参考示例应用程序中query_sgx_status函数以使用此API。有关其他详细信息,请参见sgx_enable_device。
初始化一个Enclave
在应用程序和Enclave之间建立任何可信的事务之前,需要通过uRTS提供的sgx_create_enclave来正确地创建和初始化Enclave本身。
保存和检索启动令牌
启动令牌需要传递给sgx_create_enclave进行Enclave初试化。如果启动令牌是在前一个事务中保存地,则可以直接检索和使用它。否则,你可以提供一个全0缓冲区。如果输入无效,则sgx_create_enclave将尝试创建有效地启动令牌。正确创建并初始化Enclave之后,如果令牌已被更新,你可能需要保存令牌。sgx_create_enclave地第四个参数表示是否执行了更新。
sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL);
启动令牌应该保存在每个用户的目录或注册表项中,以防在多用户环境中使用。
例如,令牌可以保存在以下任何一个位置:
ECALL/OCALL函数
这个示例演示了ECALL/OCALL函数使用的基本EDL语法,以及在Enclave中使用受信任的库。
销毁一个Enclave
要释放Enclave内存,需要调用sgx_destroy_enclave,它是由sgx_urts库提供的。它将回收EPC内存和Enclave示例使用的不可信资源。
如果发生了power transition,Enclave内存将被删除,并且所有Enclave数据都将不可访问。因此,当系统恢复时,进程内的每个ECALLs和后续的ECALL都将失败,错误代码SGX_ERROR_ENCLAVE_LOST表示Enclave由于power transition而丢失。
Intel SGX项目应具有处理可能影响其行为的power transition的能力。该项目名为PowerTrasition ,描述了一种开发Intel SGX项目的方法,该项目可以处理电源转换。有关更多信息,请参见ECALL-ERROR_Code Based Retry。
PowerTransition 演示了以下场景:一个Enclave示例由一个主线程创建并初始化,然后与其他三个子线程共享;三个子线程重复调用Enclave,在Enclave内操作秘密数据,并在Enclave外备份相应的加密数据;在所有子线程完成之后,主线程销毁Enclave并释放相关的系统资源。如果发生电源转换,一个且仅有一个线程将重新加载Enclave,并使用保存在外部的加密数据恢复Enclave中的秘密数据,然后继续执行。
基于ECALL-Error-Code重试
在Power Transition之后,将为当前ECALL返回一个Intel SGX错误代码SGX_ERROR_ENCLAVE_LOST。为了处理power transition并在不影响的情况下继续项目,你需要首先销毁无效的Enclave以释放资源,然后使用新创建和初始化的Enclave示例重试,如下图所示。
示例中的ECALLs
PowerTransition演示了两种类型的ECALLs中处理power transition:
Enclave创建后初始化ECALL
PowerTransition演示了Enclave创建后的一个初始化ECALL,如下图所示:
sgx_create_enclave是uRTS库为Enclave创建提供的一个关键API。对于sgx_create_enclave,uRTS库中已经实现了一种Power Transition处理机制。因此,不需要手动处理此API的power transition。
注意:为了集中精力处理power transition,PowerTransition假定Enclave文件和启动令牌与应用程序位于相同的目录中。有关如何正确存储启动令牌,请参见Sample Enclave。(在前面)
Enclave中正常ECALL处理机密
这是Enclave中最常见的ECALL类型。PowerTransiton演示了在主线程创建并初始化Enclave之后,在子线程中对此类ECALL的power transition处理,如下图所示。因此Enclave实例是由子线程共享的,所以需要确保一个且仅有一个子线程在power transition之后重新创建和初始化Enclave实例,而其他线程则直接使用重新创建的Enclave实例。PowerTransition通过检查Enclave ID是否更新来确认这一点。
注意:在ECALL过程中,建议经常将机密数据作为密码文本被分到Enclave之外。然后我们可以使用备份数据来恢复Enclave,以减少power transition带来的影响。
Cxx11SGXDemo项目旨在演示由Intel SGX SDK提供的Enclave内支持的C++11库特性,以及VS2017编译器支持的编译特性。这个示例为当前支持的C++11特性中的每个特性提供了实际的用例。
该示例涵盖了下表中列出的Enclave中的C++11特性的一个子集。
Headers | #include #include #include #include #include #include #include #include #include #include #include #include |
Classes | std::function, std::all_of, std::any_of, std::none_of, std::initializer_list, std::unordered_set, std::unordered_map, std::unordered_multiset, std::unordered_multimap, std::tuple, std::shared_ptr, std::unique_ptr, std::auto std::mutex, std::condition_variable |
Compiler features(编译器特性) | lambda表达式,auto, decltype, 强类型枚举类, 基于范围的语句, static_assert,新的虚函数控件, 委托构造函数,可变参数模板, 替换失败不是一个错误(SFINAE), rvalue引用和移动语义,nullptr类型 |
在Intel SGX架构中,认证指的是证明在平台上建立了特定的Enclave的过程。Intel SGX架构提供两种认证机制:
Intel SGX SDK提供应用程序用于实现认证过程的API。
本地认证
本地认证是指在交换信息之前,在同一个平台上使用Intel SGX报告机制对彼此进行身份认证。在Intel SGX应用程序中,多个Enclave可以协作执行某些功能。在两个Encalve验证对方是可信的之后,它们可以在受保护的通道上交换信息,该通道通常提供机密性、完整性和重放保护。本地认证和保护通道的建立使用基于REPORT的Diffie-Hellman Key Exchange协议。
示例代码展示了本地认证的一个示例实现,包括使用Enclave对Enclave函数调用进行受保护的通道建立的秘密消息交换。
Diffie-Hellman密钥交换库和本地认证流程
SDK中的本地认证示例使用Diffie-Hellman(DH)密钥交换库在两个Enclave之间建立受保护的通道。DH密钥交换API在sgx_dh.h中描述。密钥交换库是Intel SGX 应用程序SDK可信库的一部分。它与Enclave代码静态链接,并公开Enclave代码的API来生成和处理本地密钥交换协议消息。这个库与其他库结合在一起,并被构建到最后一个称为sgx_tservice.lib的库中。这是SDK发行版的一部分。
上图表示DH密钥交换库的使用情况。本地认证流程包括以下步骤:
途中ISV Enclave1是发起者Enclave,ISV Enclave2是回应者Enclave。
Diffie-Hellman密钥交换库和本地认证流程2.0
DH密钥交换库还公开了用于Enclave代码的DH密钥交换2.0API,以生成和处理本地密钥交换协议消息。使用在sgx_dh.h中描述的DH密钥交换2.0 APIs,将SGX_USE_LAv2_INITIATOR添加到Preprocessor Definitions选项中。
本地认证2.0流程与前面所属的步骤相似,除步骤7和10,以下介绍步骤7和10:
7.Initiator ENclave使用密钥交换库2.0 API处理Message 1,并生成DH Message 2:gb||[Report Enclave 1(h(proto_spec || gb))]SMK,report_data替换为proto_spec,其中proto_spec是:‘SGX LA’ || Ver || Rev || TARGET_SPEC || padding
10.Responder Enclave调用密钥交换库2.0 API来处理DH Message 2,并生成DH Message 3:[Report Enclave2(h(ga || proto_spec)) || Optional Payload || ga]SMK
受保护的通道建立
下图说明了两个Enclave(即源Enclave和目标Enclave之间的交互以建立会话)。应用程序通过在源Enclave中执行ECALL,传入目标Enclave的Enclave_id,从而在源Enclave和目标Enclave之间启动一个会话。在收到目标Enclave ID时,源Enclave在核心的不可信代码中执行OCALL,然后在目标Enclave中执行ECALL,以使用ECDH密钥交换协议建立交换消息所需的一个会话。
秘密消息交换和Enclave到Enclave调用
下图说明了两个Enclave之间的消息交换。在建立受保护的通道之后,会话密钥用于加密源和目标Enclave之间交换的消息中的有效负载。示例代码实现接口来加密消息的有效负载。示例代码还显示了从另一个Enclave调用函数的Enclave的实现。调用类型、目标函数ID、总输入参数长度和输入参数都封装在从调用方(源)Enclave和被调用方(目标)Enclave发送的秘密消息的有效负载中。由于一个Enclave不能访问另一个Enclave的内存,因此需要在两个Enclave之间封送所有输入输出参数,包括由一个参数间接引用的数据。示例代码使用Intel SGX SDK可信密码库加密消息的有效负载。通过这种加密,消息交换只是一个秘密,对于Enclave到Enclave的调用是封送的目标Enclave的函数id、总参数长度和所有参数。目标Enclave对有效负载进行解密并调用适当的函数。使用会话密钥对函数调用的结果加密,并将其发回源Enclave。
远程认证
一般来说,远程认证是指HW实体或HW与SW的组合获得远程提供商或某种类型的生产商的信任的概念。在Intel SGX中,远程认证包括应用程序的Enclave和Intel 提供的Quoting Enclave(QE)和Provisioning Enclave(PvE)。认证HW是Intel启用的CPU。
远程认证本身并不足以使远程方能够安全地交付其服务(机密或资产)。安全交付服务还需要安全的通信会话。在设立这样一个session期间使用了远程证明。这类似于常见的SSL握手同时包含身份验证和会话建立。
Intel SGX SDK包含如下示例代码:
SDK包含一个远程会话建立或密钥交换库(key exchange,KE),可用于极大地简化这些过程。
注意:Intel®认证服务已激活。支持Intel认证服务的沙箱版本,以支持在ISV的应用服务器中为Intel®SGX认证进行开发。有关如何在ISV应用服务器和Intel认证服务器之间建立通信的信息,请参阅Intel®认证服务文档
Intel SGX使用匿名签名方案,Intel Enhanced Privacy ID(Intel EPID)用于身份验证(例如,认证)。 所提供地密钥交换库实现了用于会话建立地类似于sigma地协议。Sigma是一种协议,包括Diffie-Hellman密钥交换,但也解决了DH地缺陷。Intel SGX使用的协议不同于IKE v1和v2中使用地Sigma协议,因为Intel SGX平台使用Intel EPID进行身份验证,而服务商使用PKI。(在Sigma中,双方都是用PKI)最后,KE库要求服务提供者在协议的身份验证部分使用ECDSA而不是RSA密钥对,而库使用ECDH进行实际的密钥交换。
远程密钥交换库(KE)
SDK中的RemoteAttestation 示例使用前面描述的远程KE库创建一个Enlave的远程认证,并在建立安全会话(密钥交换)期间使用该认证。
有不可信的和苦心的KE库。不可信的KE库是作为静态库sgx_ukey_exchange[mt].lib提供的。Intel SGX应用程序需要链接到这个库并包含头文件sgx_ukey_exchange.h,其中包含KE可信库公开的API原型。
可信KE库也作为静态库提供。作为一个可信的库,使用它的过程与不可信的KE库略有不同。主要的区别在于可信的KE库暴露了由不可信的KE库调用的ECALLs。这意味着这个库有一个对应的EDL文件sgx_tkey_exchange.edl,必须将其导入到EDL文件中,以用于使用该库的应用程序Enclave。我们可以在下面的代码片段中看到这一点,它显示了app_enclave.edl的完整内容。示例代码中应用程序Enclave的edl文件。
enclave {
from "sgx_tkey_exchange.edl" import *;
include "sgx_key_exchange.h"
include "sgx_trts.h"
trusted {
public sgx_status_t enclave_init_ra(
int b_pse,
[out] sgx_ra_context_t *p_context);
public sgx_status_t enclave_ra_close(
sgx_ra_context_t context);
};
};
值得注意的是,sgx_key_exchange.h包含特定于远程密钥交换的类型,并且必须如上面所示,以及在使用Enclave的应用程序的不可信代码中包含这些类型。最后,sgx_tkey_exchange.h是一个头文件,它包含可信库公开的API的原型,但不是ECALLs,即ISV代码在应用程序Enclave中调用的API。
远程认证和受保护会话建立
本节详细描述了远程认证示例的功能。
注意:在示例代码中,服务提供者被建模为DLL,即service_provider.dll。示例服务提供者不依赖于Intel SGX headers,类型定义、库等。这样做是为了证明在构建远程认证服务提供商时,无论如何都不需要Intel SGX。
Intel SGX应用程序通常首先从服务提供商(SP)请求服务(例如媒体流),而SP将以挑战作为相应。这在途中没有显示出来,这个图始于应用程序对challenge的反应。
注意:目前,唯一有效的扩展Intel EPID组ID为0.服务器应验证此值为0.如果Intel EPID组ID不为零,服务器将中止远程认证。
此时,已经建立了会话并交换密钥。服务提供者(SP)是否认为会话是安全的并使用它取决于S3消息所指示的平台安全属性。如果平台的安全属性符合服务提供者的标准,那么服务提供者可以使用会话密钥来安全地传递秘密,而应用程序Enlave可以在通过可信KE库上的sgx_ra_get_keys()检索会话密钥之后的任何事件使用该密钥。图中没有显示这一点,会话的结束也没有显示这一点。关闭会话需要输入应用程序Enclave并在可信的KE库上调用sgx_ra_close(),以及其他特定于应用程序Enclave的清理。
带有自定义密钥派生功能(KDF)的远程认证
默认情况下,当使用sgx_ra_get_keys API定义中描述的KDF。如果ISV需要使用一个不同于Intel SGX PSW使用的默认的KDF,ISV可以使用sgx_ra_init_ex API提供一个回调函数来生成远程认证密钥用于SIGMA协议(SMK),并由API sgx_ra_get_keys(SM,MK和VK)返回。使用不同KDF的决定是ISV的一项政策,但它应该得到ISV的安全流程的批准。
调试远程认证服务提供者(SP)
作为编写远程认证服务提供者的ISV,你可能希望调试消息流。实现这一点的一种方法是提供可重复播放和验证的预先生成的消息。但是,S1 message = (GID || ga)并不包括在Enclave内生成的随机组件ga。此外,远程认证服务SP生成一个随机的公钥+私钥对,作为其msg2生成的一部分,但不与Intel SGX进行任何交互。
为了克服这些问题,样例服务SP将修改和(仅)使用加密库。任何时候,只要密钥生成、签名或其他操作请求一个随机数,就会返回数字9。这意味着sample_libcrypto.lib 中的加密函数是预期的,并且在密码上是弱的。如果我们可以从ISV_APP中重播msg1发送,那么示例 service_provider.dll将始终生成完全相同的msg2.现在,我们有了一个足够的系统来重播ISV_SPP发送的消息,并让它验证远程服务发送的响应是否是预期的响应。
要重播消息并执行此验证流程,请在运行示例应用程序ISV_APP时传递1或2作为命令行参数。ISV_APP将忽略Intel SGX中内置检查所生成的错误。希望调试其远程认证SP的开发人员应该能够临时修改其加密子系统,使其行为类似于sample_libcrypto.lib,并重播存储在sample_messages.h中的预先计算的消息。来自它们自己的远程服务SP的响应应该与我们生成的相应相匹配,这些相应也存储在sample_messages.h中
注意:不要在生产代码中使用此示例中提供的示例密码库。
使用不同的扩展Intel®EPID组进行远程认证
Intel SGX平台软件可以生成由多个扩展的Intel EPID组的密钥签名的Quotes。在远程认证开始之前,ISV SP需要知道PSW支持哪些扩展的Intel EPID组。ISV SP将使用此信息在正确的扩展Intel EPID组中请求Quote生成和验证。API sgx_get_extended_epid_group_id返回扩展Intel EPID组ID。ISV应用程序应该使用这个API平台软件查询当前配置扩展Intel EPID组ID,并将其发送给ISV SP。然后ISV就知道哪个Intel EPID组用于远程认证。如果ISV SP不支持所提供的extended Intel EPID组,它将中止远程认证尝试。
ECDSA远程认证
Intel SGX平台软件使用Intel SGX数据中心认证原语(Intel SGX DCAP)来支持ECDSA认证。创建ECDSA认证的平台必须支持灵活发射控制(FLC)。
ECDSA认证密钥由远程认证基础设施的所有者创建和拥有,但由Intel分发证书的Intel跟密钥认证。Intel根证书证明了运行Intel SGX Enclave的平台是有效的,并且处于良好的地位。
该应用程序调用sgx_select_att_key_id来从平台外Quote验证器提供的列表中选择ECDSA认证密钥。
如有误,请指正!感激!