1

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.

  • Your code has memory leaks, and you haven't shown how the public key was transported. You also have a confusion between RSA_MOD_SIZE and RSA_PUBLIC_SIZE. – user207421 Mar 08 '22 at 23:14
  • RSA_MOD_SIZE and RSA_PUBLIC_SIZE are both #define with the same size, I'm not sure what you mean by public key transportation, I have tried sending a pointer through an argument to use memcpy to return the value back to the untrusted area, which blocks the enclave. The code I've posted uses an Ocall that sends a pointer from the trusted to the untrusted area. The memory leaks might affect it, but considering the memory leaks are of a few bytes, I'm not sure that is what is affecting it, but I will do my best to fix those regardless. – mute_police Mar 09 '22 at 08:59
  • And as previously stated in the question, If I encrypt & Decrypt in the same function, everything happens correctly. (Including RSA/pair generation), which makes me believe that is not the problem. – mute_police Mar 09 '22 at 11:30

1 Answers1

0

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.