英特尔SGX RemoteAttestation:无法在客户端验证SP的签名

问题描述

基于this source,我想在Node JS服务器中实现服务提供者功能。但是,即使我认为我遵循了RA Sample中的算法,启用SGX的客户端(在我的情况下,是sgxsdk SampleCode中RemoteAttestation项目的isv_app)也不接受SP的MSG2,从而产生0x2003错误(无效签名),由sgx_ra_proc_msg2_ex函数返回。

生成msg2的JS代码:

const crypto = require('crypto');
const aesCmac = require('node-aes-cmac').aesCmac;
const EC = require('elliptic').ec;
const ec = new EC('p256');
const pepECDH = crypto.createECDH('prime256v1');

const SPID = 'C8C56121818E4F00FE4AB868389F3059';
const X_LENGTH = 32;
const Y_LENGTH = 64;

//Utilities
const swap = function(l_index,h_index,array) {
   let aux;
   while (l_index < h_index) {
     aux = array[l_index];
     array[l_index] = array[h_index];
     array[h_index] = aux;
     l_index++;
     h_index--;
   }
 };

const changeKeyEndianess = function(key) {
  swap(0,X_LENGTH - 1,key);
  swap(X_LENGTH,Y_LENGTH - 1,key);
    };

const generateCMAC = function(key,data) {
  const options = { returnAsBuffer: true };
  return aesCmac(key,data,options);
};

const deriveKey = function(sharedKey,label) {
  swap(0,sharedKey.length - 1,sharedKey);
  const key0s = Buffer.from('00000000000000000000000000000000','hex');

  const cmacKey0s = generateCMAC(key0s,Buffer.from(sharedKey));
  //0x01 || SMK || 0x00 || 0x80 || 0x00
  const auxInfo = Buffer.concat([
    Buffer.from('01','hex'),Buffer.from(label),Buffer.from('008000',]);
  const derivedKey = generateCMAC(cmacKey0s,auxInfo);
  return derivedKey;
};

//1. Generate a random EC key using the P-256 curve. This key will become Gb.
pepECDH.generateKeys();
var Gb_BE = pepECDH.getPublicKey().slice(1); //remove 0x04,used only for elliptic library internals
var Gb_LE = Gb_BE;
changeKeyEndianess(Gb_LE); //pep public key now in Little Endian
//2. Derive the key derivation key (KDK) from Ga and Gb:
//2.1. Compute the shared secret using the client's public session key,Ga,//and the service provider's private session key (obtained from Step 1),Gb.
// The result of this operation will be the x coordinate of Gab,denoted as Gabx.
var Ga_raw = msg.slice(0,64); //client's public key,Little Endian
var Ga_LE = Buffer.from(Ga_raw);
let Ga_BE = Ga_LE;
changeKeyEndianess(Ga_BE); //done for computeSecret function (to Big Endian)
Ga_BE = [0x04,...Ga_BE]; //the elliptic lib requires 0x04 at the beginning of the key to work properly
var Gabx_BE = pepECDH.computeSecret(new Buffer(Ga_BE));
//2.2. Convert Gabx to little-endian byte order by reversing its bytes.
var Gabx_LE = Gabx_BE;
changeKeyEndianess(Gabx_LE); //now in little-endian
//2.3. Perform an AES-128 CMAC on the little-endian form of Gabx
//using a block of 0x00 bytes for the key.
//Derive the SMK from the KDK by performing an AES-128 CMAC on the byte sequence:
//0x01 || SMK || 0x00 || 0x80 || 0x00 --> SMK is a literal string without quotes
var derivedKeySMK = deriveKey(Gabx_LE,'SMK');
//1. Determine the quote type that should be requested from the client
//(0x0 for unlinkable,and 0x1 for linkable). Note that this is a service provider
//policy decision,and the SPID must be associated with the correct quote type.
var quoteType = Buffer.from('0000','hex');
//2. Set the KDF_ID. Normally this is 0x1.
var kdfID = Buffer.from('0100','hex');
var spid = Buffer.from(SPID,'hex');
//3. Calculate the ECDSA signature of:
//Gbx || Gby || Gax || Gay
//(traditionally written as r || s) with the service provider's EC private key.
var concatenatedPublicKeys = Buffer.concat([Gb_LE,Ga_LE]);
var pepPrivateKey = pepECDH.getPrivateKey();
var keysHash = crypto
  .createHash('sha256')
  .update(concatenatedPublicKeys)
  .digest();

var SigSP_BE = ec.sign(keysHash,pepPrivateKey,{ canonical: true });
var r = SigSP_BE.r.toBuffer('le',32);
var s = SigSP_BE.s.toBuffer('le',32);
var SigSP_LE = Buffer.concat([r,s]);
//4. Calculate the AES-128 CMAC of:
//Gb || SPID || Quote_Type || KDF_ID || SigSP
//using the SMK (derived in Step 3) as the key.
var toCmac = Buffer.concat([Gb_LE,spid,quoteType,kdfID,SigSP_LE]);
var Cmaced = generateCMAC(derivedKeySMK,toCmac);

然后,SP与IAS联系并接收带有空SigRL的代码200。客户端(isv_app)的日志下方:

Sent MSG1 to remote attestation service provider. Received the following MSG2:
176 bytes:
{
0x2,0x0,0xa8,0x7b,0x7f,0xe3,0x71,0x6,0x6f,0xf2,0xd4,0x86,0x14,0xa6,0x87,0x1a,0x50,0x5f,0x9b,0x13,0x11,0x7a,0x73,0xaa,0x8a,0x80,0xad,0xbc,0xcb,0x5a,0xdb,0xf4,0x77,0x2f,0x5c,0xb9,0x12,0xf3,0x20,0x47,0x34,0x88,0x1,0x75,0x46,0xab,0xb1,0x24,0x8d,0x49,0xa0,0xf9,0xe6,0x43,0x74,0x4b,0xe9,0x1b,0x5b,0xba,0x67,0xd,0x5,0x16,0xc8,0xc5,0x61,0x21,0x81,0x8e,0x4f,0xfe,0x4a,0xb8,0x68,0x38,0x9f,0x30,0x59,0xea,0x1c,0x72,0xa5,0xb3,0x35,0xa3,0x4d,0xd1,0xe1,0xf8,0xb2,0x17,0x40,0xd0,0x65,0xc3,0x54,0xc,0xc9,0x10,0xcc,0xa9,0x90,0x91,0x63,0x6a,0x70,0xd5,0xed,0xe2,0xa4,0x3c,0x57,0x84,0x92,0xc0,0x5e,0x28,0x31,0x7,0x99,0xb5,0x3f,0x5d,0x23,0x55,0x6b,0x9,0x8,0xf6,0x9a,0x0 
}

A more descriptive representation of MSG2:
RESPONSE TYPE: 0x2
RESPONSE STATUS: 0x0 0x0
RESPONSE BODY SIZE: 168
MSG2 gb - 64 bytes:
{
0x7b,0x16 
}
MSG2 spid - 16 bytes:
{
0xc8,0x59 
}
MSG2 quote_type : 0
MSG2 kdf_id : 1
MSG2 sign_gb_ga - 64 bytes:
{
0xea,0x0 
}
MSG2 mac - 16 bytes:
{
0xb5,0xfe 
}
MSG2 sig_rl - 
( null )

Error,call sgx_ra_proc_msg2_ex fail. p_msg3 = 0x(nil) [main]. Ret: 0x00002003
Call enclave_ra_close success.
Enter a character before exit ...

我正在Ubuntu 18.04上使用nodejs v14.10.0。使用的JS库:

"elliptic": "^6.5.3","node-aes-cmac": "^0.1.1",

我已经尝试了数千次反转每个变量中的字节,但是没有成功。错误的原因可能是什么?我是不是根据SGX RA协议生成了MSG2,还是我在JS中错误地使用了加密技术?

任何帮助表示赞赏。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...