概要
本文的目标读者是SGX的开发者,撰写此文旨在帮助他们升级他们的Intel® SGX远程认证服务API到V2版本(V1版本将于2018年1月份弃用),如果你想更多的了解什么是SGX,或者想更多的了解Intel® SGX远程认证服务的相关细节(工作原理,如何申请测试服务等),请参阅此文最后的参考文献。
什么是Intel® SGX远程认证服务
Intel® SGX除了为离线应用提供硬件级别的保护之外,还为需要联网的应用,比如DRM应用,银行交易应用等提供“客户端向服务器证明自己合法性”的能力,我们称这个过程为远程认证(Remote Attestation)。在这个过程中,客户端的软硬件平台信息,以及相关Enclave的指纹信息等将会首先发送到开发者的服务器(Service Provider),然后由开发者的服务器转发给SGX的远程认证服务器(Attestation Service),SGX远程认证服务器将会对收到的信息进行合法性验证,并将验证结果返回给开发者的服务器,此时开发者的服务器便可得知发起验证的客户端是否可信,并采取对应的下一步行动。
Intel® SGX 远程认证服务 API
在远程认证的过程中,开发者的服务器与SGX远程认证服务器之间采用标准的TLS网络通信协议(最低支持TLS1.2版本),SGX远程认证服务器以REST API的形式向开发者服务器提供服务,让开发者服务器可以实现诸如提交远程认证,获取远程认证结果,获取EPID吊销列表等相关功能。我们称这些REST API为远程认证服务API。目前为远程认证服务API已经发布V2版本,并弃用之前的V1版本,开发者需要尽快更新他们的服务器相关实现,对接到V2版本。
如何升级Intel® SGX 远程认证服务 API 到V2版本
首先,开发者需要将API请求发送到V2版本对应的URL地址。比如,在V1中,我们获取SigRL时,我们发送请求到/attestation/sgx/v1/sigrl/{gid},当升级到V2版本时,我们需要将对应的请求发送到/attestation/sgx/v2/sigrl/{gid}这个地址。这一点适用于其它所有API。
另外一个比较大的改动是远程认证报告签名验证机制的改变。在V1版本中,我们通过/attestation/sgx/v1/report来获取认证报告,报告的签名包含在X-IASReport-Signature这个response header中。提取了远程认证报告签名之后,我们读取预存在开发者服务器本机的SGX远程认证服务器的公钥,然后用公钥对签名进行验证。而在V2版本中,当我们获取远程认证报告(/attestation/sgx/v2/report)时,在返回的Response Header中会多附加一个X-IASReport-Signing-Certificate的项目,这个项目中包含了远程认证报告签名所用的证书链,我们首先需要用预存在开发者服务器本机的SGX远程认证根证书对该证书链的合法性进行验证,在确保该证书链合法的前提下,再用该证书链对远程认证报告的签名进行验证。具体的实现可以参考以下代码片段(注:以下代码基于openssl V1.0.2j开发,仅供参考,不能直接作为真实的实现):
1.加载预存在开发者服务器本机的SGX远程认证根证书
// 加载Intel远程认证服务的根证书ra.crt(此证书需要事先预置在开发者服务器本机) BIO *bio_ra = BIO_new_file("ra.crt","r"); X509 *cert_ra = PEM_read_bio_X509(bio_ra,NULL,NULL,NULL);
2.用SGX远程认证根证书验证证书链的合法性
/* “X-IASReport-Signing-Certificate”这个http header中包含了证书链,此处略去了 提取证书链到str_cert_chain的代码 */ // 用步骤1中加载的Intel根证书验证证书链str_cert_chain的合法性 bool res_cert_chain_verify = false; X509_STORE *store; X509_STORE_CTX *ctx; store = X509_STORE_new(); ctx = X509_STORE_CTX_new(); X509_STORE_add_cert(store, cert_ra); BIO *bio_cert_chain = BIO_new_mem_buf((void*)str_cert_chain, -1); X509_INFO *itmp; STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(bio_cert_chain, NULL, NULL, NULL); for (int i = 0; i < sk_X509_INFO_num(inf); i++) { itmp = sk_X509_INFO_value(inf, i); if (itmp->x509) { X509_STORE_CTX_init(ctx, store, cert_ra, NULL); if(! X509_verify_cert(ctx) ){ res_cert_chain_verify = false; }else if(i == sk_X509_INFO_num(inf) -1){ res_cert_chain_verify = true; } X509_STORE_CTX_cleanup(ctx); } } sk_X509_INFO_pop_free(inf, X509_INFO_free); BIO_free(bio_cert_chain); X509_STORE_CTX_free(ctx); X509_STORE_free(store);
3.用证书链验证远程认证报告签名的合法性
bool res_sig_verify = false; if( res_cert_chain_verify ){ // 用IAS公钥验证远程报告签名 // 从证书链str_cert_chain中提取对报告签名的IAS公钥 BIO *bio_sp = BIO_new(BIO_s_mem()); BIO_write(bio_sp, str_cert_chain, strlen(str_cert_chain)); X509 *cert_sp = PEM_read_bio_X509(bio_sp, NULL, NULL, NULL); EVP_PKEY *pubkey_sp = X509_get_pubkey(cert_sp); // 用IAS公钥验证远程报告的签名 RSA *rsa = EVP_PKEY_get1_RSA(pubkey_sp); QByteArray digest = QCryptographicHash::hash(reportBody, QCryptographicHash::Sha256); res_sig_verify = RSA_verify(NID_sha256, (unsigned char*)digest.data(), SHA256_DIGEST_LENGTH, (unsigned char*)signature.data(), 256, rsa); BIO_free_all(bio_sp); X509_free(cert_sp); EVP_PKEY_free(pubkey_sp); }
总结
SGX远程认证服务提供了必要的基础设施,让服务器可以判断正在请求服务的客户端是否处于安全可信的环境中 (硬件+软件) ,并且建立加密的信道,从而可以安全的将机密数据下发到可信的客户端,以及拒绝为不可信的客户端提供服务。作为远程认证服务的升级,API版本2在兼顾API兼容性的同时,完善和加强了远程认证报告的验证流程,是一次非常有意义的升级。
参考文献
Intel® Software Guard Extensions (Intel® SGX): https://software.intel.com/zh-cn/sgx/details
Attestation Service for Intel® Software Guard Extensions (Intel® SGX) API Documentation:https://software.intel.com/sites/default/files/managed/7e/3b/ias-api-spec.pdf
Intel® Software Guard Extensions Remote Attestation End-to-End Example: https://software.intel.com/zh-cn/articles/intel-software-guard-extensions-remote-attestation-end-to-end-example
关于作者
裴凡江是英特尔软件与服务事业部的一名应用软件工程师,专注于安全领域。主要负责与开发者一起合作,将英特尔平台的相关安全技术(例如SGX)应用到开发者的产品中,以实现安全相关的应用场景(比如指纹支付),或者提高应用本身的安全性。