将公钥 Mod 从 Intel SGX Enclave 复制到不受信任的区域

发布于 2025-01-13 01:51:54 字数 2562 浏览 2 评论 0原文

我正在开发一个 C 伪 API,其中 Java 代码通过 JNI 调用 C 代码,并在 JNI 中连接到 Intel SGX Enclave。我有一个函数,可以在其中创建一个 RSA 密钥对以供进一步使用。

创建 RSA 对:

sgx_status_t create_rsa_pair(){
unsigned char p_n[RSA_MOD_SIZE];
unsigned char p_d[RSA_MOD_SIZE];
unsigned char p_p[RSA_MOD_SIZE];
unsigned char p_q[RSA_MOD_SIZE];
unsigned char p_dmp1[RSA_MOD_SIZE];
unsigned char p_dmq1[RSA_MOD_SIZE];
unsigned char p_iqmp[RSA_MOD_SIZE];

int n_byte_size = RSA_MOD_SIZE;
long e = 65537;


sgx_status_t ret_create_key_params = sgx_create_rsa_key_pair(n_byte_size, sizeof(e), p_n, p_d, (unsigned char*)&e, p_p, p_q, p_dmp1, p_dmq1, p_iqmp);

if (ret_create_key_params != SGX_SUCCESS) {
    ocall_print("Key param generation failed");
}

//void *private_key = NULL;

sgx_status_t ret_create_private_key = sgx_create_rsa_priv2_key(n_byte_size, sizeof(e), (unsigned char*)&e, p_p, p_q, p_dmp1, p_dmq1, p_iqmp, &private_rsa);

if(ret_create_private_key != SGX_SUCCESS) {
    ocall_print("Private key generation failed");
}

void *public_key = NULL;

sgx_status_t ret_create_public_key = sgx_create_rsa_pub1_key(n_byte_size, sizeof(e), p_n, (unsigned char*)&e, &public_key);

if(ret_create_public_key != SGX_SUCCESS) {
    ocall_print("Public key generation failed");
}

//Copy the result and send it in an ocall.
uint8_t* ocall_mod = (uint8_t*)malloc(RSA_MOD_SIZE);
uint8_t* ocall_exp = (uint8_t*)malloc(sizeof(long));
memcpy(ocall_mod,p_n,RSA_MOD_SIZE);
memcpy(ocall_exp,&e,sizeof(long));
printf("pre/ocall_mod::");
for(int i = 0; i < RSA_MOD_SIZE;i++){
    printf("%"PRIu8",",ocall_mod[i]);
}
printf("\n");
ocall_return_pubkey(ocall_mod,ocall_exp);
return SGX_SUCCESS;
}

Ocall 代码:

void ocall_return_pubkey(uint8_t* key_mod,long *key_exp){
  printf("Post/Ocall key-mod:: ");
  for(int i = 0; i < RSA_PUBLIC_SIZE;i++)
    printf("%"PRIu8",",key_mod[i]);
   printf("\n");

现在,如果我编译此代码并检查终端结果:

pre/ocall_mod::199,100,141,174,148,185,21,88,102,216,116,190,170,232,156,196,107,78,228,1,5,38,92,154,20,11,234,149,74,19,254,237,240,223,145,92,188,248,25

Post/Ocall key-mod:: 199,0,0,0,0,0,0,0,0,0,57,44,0,127,0,0,0,83,144,167,247,127,0,0,9,107,99,240,0,0,0,0,172,141,193,3,0,0,0,0,68,83,144,167,247

为了简洁起见,我仅发布了 mod 的一部分,但该信息似乎已损坏或删除,特别是考虑到大量 0 。

我尝试通过 Ecall 传递一个指针作为参数,以便通过它接收我的结果,但是(至少在这种情况下),由于此副本从可信内存到不可信内存,飞地会阻止程序执行,这意味着发送从 enclave 通过 ocall 的指针似乎是唯一的选择。对此有什么帮助或提示吗? 提前致谢。

编辑:在一个单独的说明中,如果我编写的所有代码全部用于单个函数(加密、解密+创建 AES 密钥),那么我编写的所有代码都可以工作,但是如果它被分成多个函数,那么由于某种原因,它会失败。

I am developing a C pseudo-API in which Java code calls C code through the JNI, in which it connects to an Intel SGX Enclave. I have a function in which I create an RSA-Key pair to be used further on.

Create RSA Pair:

sgx_status_t create_rsa_pair(){
unsigned char p_n[RSA_MOD_SIZE];
unsigned char p_d[RSA_MOD_SIZE];
unsigned char p_p[RSA_MOD_SIZE];
unsigned char p_q[RSA_MOD_SIZE];
unsigned char p_dmp1[RSA_MOD_SIZE];
unsigned char p_dmq1[RSA_MOD_SIZE];
unsigned char p_iqmp[RSA_MOD_SIZE];

int n_byte_size = RSA_MOD_SIZE;
long e = 65537;


sgx_status_t ret_create_key_params = sgx_create_rsa_key_pair(n_byte_size, sizeof(e), p_n, p_d, (unsigned char*)&e, p_p, p_q, p_dmp1, p_dmq1, p_iqmp);

if (ret_create_key_params != SGX_SUCCESS) {
    ocall_print("Key param generation failed");
}

//void *private_key = NULL;

sgx_status_t ret_create_private_key = sgx_create_rsa_priv2_key(n_byte_size, sizeof(e), (unsigned char*)&e, p_p, p_q, p_dmp1, p_dmq1, p_iqmp, &private_rsa);

if(ret_create_private_key != SGX_SUCCESS) {
    ocall_print("Private key generation failed");
}

void *public_key = NULL;

sgx_status_t ret_create_public_key = sgx_create_rsa_pub1_key(n_byte_size, sizeof(e), p_n, (unsigned char*)&e, &public_key);

if(ret_create_public_key != SGX_SUCCESS) {
    ocall_print("Public key generation failed");
}

//Copy the result and send it in an ocall.
uint8_t* ocall_mod = (uint8_t*)malloc(RSA_MOD_SIZE);
uint8_t* ocall_exp = (uint8_t*)malloc(sizeof(long));
memcpy(ocall_mod,p_n,RSA_MOD_SIZE);
memcpy(ocall_exp,&e,sizeof(long));
printf("pre/ocall_mod::");
for(int i = 0; i < RSA_MOD_SIZE;i++){
    printf("%"PRIu8",",ocall_mod[i]);
}
printf("\n");
ocall_return_pubkey(ocall_mod,ocall_exp);
return SGX_SUCCESS;
}

Ocall code:

void ocall_return_pubkey(uint8_t* key_mod,long *key_exp){
  printf("Post/Ocall key-mod:: ");
  for(int i = 0; i < RSA_PUBLIC_SIZE;i++)
    printf("%"PRIu8",",key_mod[i]);
   printf("\n");

Now, If I compile this and check terminal results:

pre/ocall_mod::199,100,141,174,148,185,21,88,102,216,116,190,170,232,156,196,107,78,228,1,5,38,92,154,20,11,234,149,74,19,254,237,240,223,145,92,188,248,25

Post/Ocall key-mod:: 199,0,0,0,0,0,0,0,0,0,57,44,0,127,0,0,0,83,144,167,247,127,0,0,9,107,99,240,0,0,0,0,172,141,193,3,0,0,0,0,68,83,144,167,247

I've posted only a portion of the mod for brevity's sake, but the information does seem to be corrupted or deleted, especially considering the large number of 0's.

I've tried passing a pointer throught the Ecall as an argument in order to receive my result through it, but (at least in this scenario), the enclave blocks the program execution due to this copy from trusted to untrusted memory, meaning that sending a pointer from the enclave through an ocall seems like the only option. Any help or tips for this?
Thanks in advance.

Edit: On a separate note, All the code I've written works if all used in a single function (Encryption, Decryption + Creation of an AES key), but if it is separated into multiple functions, it fails, for some reason.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

浅紫色的梦幻 2025-01-20 01:51:54

使用 ocalls 返回信息并不是解决此问题的方法。

虽然我之前的想法失败了,但解决方法是向函数参数添加一个指针及其大小,以便复制结果。

所以
Enclave EDL

public sgx_status_t whatever([out,size=output_size]uint8_t* output,size_t output_size)

现在,请记住,output_size 不是写入的字节数。通过在使用 Ecall 之前设置 output_size = 0,enclave 内的相应缓冲区将为 NULL,在使用时返回段错误。
如果在任何时候您需要写入的字节数,即加密,您应该使用以下内容:

sgx_status_t encrypt([out,size=output_size]uint8_t *output, size_t output_size, [out,size=num_size]size_t* bytes_written,size_t num_size);

其中 num_size 应等于 sizeof(size_t)。

我能够解决这个问题,希望对你们有帮助。

Using ocalls to return information is not the way to go for this.

While I had failed previously with this Idea, the way to go is by adding a pointer and its size to a functions arguments in order to copy the results.

so
Enclave EDL

public sgx_status_t whatever([out,size=output_size]uint8_t* output,size_t output_size)

Now, bear in mind that output_size is not the number of bytes written. By setting output_size = 0 before using the Ecall, the corresponding buffer inside the enclave will be NULL, returning a segfault upon usage.
if at any point you require the number of bytes written, i.e encryption, you should use the following:

sgx_status_t encrypt([out,size=output_size]uint8_t *output, size_t output_size, [out,size=num_size]size_t* bytes_written,size_t num_size);

In which num_size should be equal to sizeof(size_t).

I was able to solve this problem, Hope it helps you guys.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文