Intel® Software Guard Extensions (Intel® SGX)
Discussion board focused on hardware-based isolation and memory encryption to provide extended code protection in solutions.

Asymmetric cryptography in Enclave

damgaard22
Beginner
1,406 Views

I have been trying to find a way to generate a public and private key inside an enclave to encrypt and decrypt incoming data. 

I found sgx_create_rsa_key_pair() in sgx_tcrypto, though i am having a hard time getting it working.
Do you have any examples of creating RSA keys or should i be doing this in another way?

Best Regards,
Mads

0 Kudos
1 Solution
JesusG_Intel
Moderator
1,324 Views

Hello damgaard22,

 

We finally figured it out. When you encrypt the message using sgx_rsa_pub_encrypt_sha256 and you send the size of the input in the last parameter, you are using sizeof(pin_data). In your code, pin_data is a "char *" so the size of "char *" is 8 bytes. For this parameter, you have to send the size of the input itself. In this case, you can use strlen(pin_data) instead of sizeof(pin_data).

 

This is a good discussion  on private and public key lengths.

 

 

View solution in original post

8 Replies
JesusG_Intel
Moderator
1,390 Views

Hello Daamgard22,


Please provide source code and error messages to help us diagnose your issue.


damgaard22
Beginner
1,380 Views

Hi Jesus,

Sure.
This is my code in Enclave.cpp
Everything seems to be linked and imported correctly since i spend some time getting that right.
I am importing sgx_tcrypto.h
ocall_print is just a call to printf that also appends a newline

The code example prints:
"
Encryption failed
1
"

Indicating an error of "SGX_ERROR_UNEXPECTED" according to sgx_error.h
It also seems that the private and public key were created successfully as it fails at encryption.

unsigned char p_n[256];
unsigned char p_d[256];
unsigned char p_p[256];
unsigned char p_q[256];
unsigned char p_dmp1[256];
unsigned char p_dmq1[256];
unsigned char p_iqmp[256];

int n_byte_size = 256;
int e_byte_size = 4;
long e = 65537;


sgx_status_t ret_create_key_params = sgx_create_rsa_key_pair(n_byte_size, e_byte_size, 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");
    ocall_print(std::to_string(ret_create_key_params).c_str());
} else {
    ocall_print((char *) p_q);
}

void *private_key[256];

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

if ( ret_create_private_key != SGX_SUCCESS) {
    ocall_print("Private key generation failed");
    ocall_print(std::to_string(ret_create_private_key).c_str());
}

void *public_key[256];

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

if ( ret_create_public_key != SGX_SUCCESS) {
    ocall_print("Public key generation failed");
    ocall_print(std::to_string(ret_create_public_key).c_str());
}

const char * pin_data = "Hello World!";
size_t out_len = 256;
unsigned char * pout_data = NULL;
ocall_print("Public key");

sgx_status_t ret_encrypt = sgx_rsa_pub_encrypt_sha256(&public_key, pout_data, &out_len, (unsigned char *)pin_data, sizeof(pin_data));

if ( ret_encrypt != SGX_SUCCESS) {
    ocall_print("Encryption failed");
    ocall_print(std::to_string(ret_encrypt).c_str());
}

 

JesusG_Intel
Moderator
1,374 Views

Hello daamgard22,


I found this example, https://cpp.hotexamples.com/examples/-/-/sgx_sha256_msg/cpp-sgx_sha256_msg-function-examples.html#0xbe1627ef0ca4806adec49545040c9a3e11a5f3b49b8fbf268df2aa46f9e6fd9a-307,,836, that demonstrates how to use sgx_rsa_pub_encrypt_sha256.


You just need to make three small changes to make your code work:


//void *public_key[256]

void *public_key = NULL;

sgx_status_t ret_create_public_key = sgx_create_rsa_pub1_key(n_byte_size, e_byte_size, p_n, (unsigned char*)&e, &public_key); //add "&" to public_key

...

sgx_status_t ret_encrypt = sgx_rsa_pub_encrypt_sha256(public_key, pout_data, &out_len, (unsigned char *)pin_data, sizeof(pin_data)); //remove "&" from public_key


damgaard22
Beginner
1,369 Views

Thanks, that got me a lot further!

Though i am now having trouble decrypting it correctly.
When decrypting, the original "Hello World!" becomes "Hello Wo" which means it is missing 4 chars.
Looking at the output it does also seem that the "decrypted_out_len" that indicates the length of the decrypted data is 8 bytes instead of the expected 12 bytes.

Here is the updated code:

unsigned char p_n[256];
unsigned char p_d[256];
unsigned char p_p[256];
unsigned char p_q[256];
unsigned char p_dmp1[256];
unsigned char p_dmq1[256];
unsigned char p_iqmp[256];

int n_byte_size = 256;
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");
    ocall_print(std::to_string(ret_create_key_params).c_str());
} else {
    ocall_print((char *) p_q);
}

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_key);

if ( ret_create_private_key != SGX_SUCCESS) {
    ocall_print("Private key generation failed");
    ocall_print(std::to_string(ret_create_private_key).c_str());
}

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");
    ocall_print(std::to_string(ret_create_public_key).c_str());
}

char * pin_data = "Hello World!";
size_t out_len = 0;

sgx_status_t ret_get_output_len = sgx_rsa_pub_encrypt_sha256(public_key, NULL, &out_len, (unsigned char *)pin_data, sizeof(pin_data));

if ( ret_get_output_len != SGX_SUCCESS) {
    ocall_print("Determination of output length failed");
    ocall_print(std::to_string(ret_get_output_len).c_str());
}

unsigned char pout_data[out_len];

sgx_status_t ret_encrypt = sgx_rsa_pub_encrypt_sha256(public_key, pout_data, &out_len, (unsigned char *)pin_data, sizeof(pin_data));

if ( ret_encrypt != SGX_SUCCESS) {
    ocall_print("Encryption failed");
    ocall_print(std::to_string(ret_encrypt).c_str());
} else {
    ocall_print(std::to_string(out_len).c_str());
}

size_t decrypted_out_len = 0;

sgx_status_t ret_determine_decrypt_len = sgx_rsa_priv_decrypt_sha256(private_key, NULL, &decrypted_out_len, pout_data, sizeof(pout_data));

if ( ret_determine_decrypt_len != SGX_SUCCESS) {
    ocall_print("Determination of decrypted output length failed");
    ocall_print(std::to_string(ret_determine_decrypt_len).c_str());
}

unsigned char decrypted_pout_data[decrypted_out_len];

sgx_status_t ret_decrypt = sgx_rsa_priv_decrypt_sha256(private_key, decrypted_pout_data, &decrypted_out_len, pout_data, sizeof(pout_data));

if ( ret_decrypt != SGX_SUCCESS) {
    ocall_print("Decryption failed");
    ocall_print(std::to_string(ret_decrypt).c_str());
} else {
    ocall_print("Decrypted MESSAGE:");
    ocall_print((char *) decrypted_pout_data);
    ocall_print(std::to_string(decrypted_out_len).c_str());
}


This outputs (With comments):
256 # out_len
Decrypted MESSAGE:
Hello Wop28c� # Seems like it correctly decrypted 8 bytes and the rest looks weird
8 # decrypted_out_len (Should be 12 bytes afaik as there are 12 bytes in "Hello World!"

JesusG_Intel
Moderator
1,357 Views

Hello daamgard,


You seem to be doing everything right and I cannot figure out why the output is only 8 bytes in length. I will confer with engineering and let you know what they find.


damgaard22
Beginner
1,330 Views

Hi Jesus,

Any updates on this?

Also is there a way to get the length of the keys?
For example i want to send the public key to another party but i do not know how to find the size of the  public key.

All your help is greatly appreciated.

JesusG_Intel
Moderator
1,325 Views

Hello damgaard22,

 

We finally figured it out. When you encrypt the message using sgx_rsa_pub_encrypt_sha256 and you send the size of the input in the last parameter, you are using sizeof(pin_data). In your code, pin_data is a "char *" so the size of "char *" is 8 bytes. For this parameter, you have to send the size of the input itself. In this case, you can use strlen(pin_data) instead of sizeof(pin_data).

 

This is a good discussion  on private and public key lengths.

 

 

JesusG_Intel
Moderator
1,312 Views

This thread has been marked as answered and Intel will no longer monitor this thread. If you want a response from Intel in a follow-up question, please open a new thread.


Reply