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
3,564 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
3,482 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

0 Kudos
8 Replies
JesusG_Intel
Moderator
3,548 Views

Hello Daamgard22,


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


0 Kudos
damgaard22
Beginner
3,538 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());
}

 

0 Kudos
JesusG_Intel
Moderator
3,532 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


0 Kudos
damgaard22
Beginner
3,527 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!"

0 Kudos
JesusG_Intel
Moderator
3,515 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.


0 Kudos
damgaard22
Beginner
3,488 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.

0 Kudos
JesusG_Intel
Moderator
3,483 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.

 

 

0 Kudos
JesusG_Intel
Moderator
3,470 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.


0 Kudos
Reply