0

Good evening, I am building a java project in which it communicates with an Intel SGX Enclave via JNI, and sees information it sends sealed by the enclave.

However, decrypting information returns information I cannot understand, and at this point, I believe it to be due to size differences,but I dont exactly understand it.

So, I know that Sizeof(char*) is equivalent to 1 byte, just like sizeof(jbyte). However, sizeof(jchar) is equivalent to 2 bytes.

After acquiring this knowledge, I decided to implement the Sealing (Or encryption) function by having it take a JByteArray in order to circumvent this problem. Should this byte[] be given in UTF-8 or UTF-16? Does it affect the function overall?

Here is an example of what I do:

JNIEXPORT jbyteArray JNICALL Java_sgxUtils_SgxFunctions_jni_1sgx_1seal_1info
  (JNIEnv * env, jobject, jbyteArray jArray){
    
   //Create a char* from the given byte array.   
   jbyte *b = env->GetByteArrayElements(jArray,NULL);
   int StringSize = env->GetArrayLength(jArray);
   char* c = (char*)malloc(sizeof(char) * StringSize);
   memcpy(c,b,StringSize);
   
   //Calculate the size of the encryption.
   size_t sealed_size = sizeof(sgx_sealed_data_t) + StringSize;

   //Create a uint8_t pointer to store the sealed information
   uint8_t* sealed_data = (uint8_t*)malloc(sealed_size);

   sgx_status_t ecall_status; //Store the status of the ecall.
   seal(global_eid, &ecall_status,(uint8_t*)&c,StringSize, sgx_sealed_data_t*)sealed_data,sealed_size);

   //Produce the jbyteArray to return:
    jbyte* jresult = (jbyte*)calloc(sizeof(jbyte),sealed_size);
    for(int i = 0 ; i < sealed_size ;i++){
        jresult[i] = (jbyte)sealed_data[i];
    }

    jbyteArray jArray2 = env->NewByteArray(sealed_size+1);
    env->SetByteArrayRegion(jArray2,0,sealed_size,jresult);
    
    return jArray2;

Does using uint8_t affect the sealing? I am at a loss of what it might be. The way I receive this byte[] in java is as follows:

byte[] c = sgx.jni_sgx_seal_info("toEncrypt".getBytes(Charset.forName("UTF-8")));
String sealed = new String(c,StandardCharsets.UTF_8);

Does anyone know what could be affecting this? The output after unsealing (decryption) currently stands as �|(�

  • Encrypting strings in memory is usually a waste of time, because the value will be unencrypted somewhere. – Charles Feb 13 '22 at 16:03
  • This is just a test function I am implementing to be imported by a larger project. Right now, what I wish to do, is to be able to seal and unseal information to make sure the code works as intended. – mute_police Feb 13 '22 at 16:09
  • 2
    An important point for finding problems in code, is *exactness*. You don’t know where the problem is, hence, you can not redact the code to omit “non important” stuff, as you don’t know what is important. So the only reasonable way to simplify, is by re-checking the simplified code, for whether it still reproduces the problem. The code, you’ve posted, obviously has never seen a compiler. But despite the unbalanced parenthesis at your `seal` method invocation, it looks highly suspicious that you are using `&c`, a pointer to a pointer. – Holger Feb 14 '22 at 09:29
  • The code had seen the compiler, the one I posted was just something I copied to give context. The pointer you mentioned was the problem, I was sealing the memory address and not the information within it. Thanks for the help! – mute_police Feb 14 '22 at 09:43
  • 2
    Note that `memcpy(c,b,StringSize)` assumes that `jbyte` and `char` are the same, while casting `char*` to `uint8_t*` assumes that `char` and `uint8_t` are the same. In other words, there is no need to pretend to perform conversions. If `seal` does only read the source data, there’s no need for a copy either, you could pass `(uint8_t*)b` directly to it. The same applies to the manual copying loop after `seal`; the way calculate and use `sealed_size` implies that the datatypes must match and the copying loop is obsolete. Just pass `sealed_data` to `SetByteArrayRegion`. – Holger Feb 14 '22 at 12:45

1 Answers1

1

You can't convert random bytes (such as produced by encryption) into UTF-8 (or many multi-byte encodings, 8-bit single byte encodings are fine). The String will most likely become corrupted, as there are byte sequences describing illegal characters, they will be replaced with 0xFFFE or i.e. he unicode replacement character.

So you will need to keep the byte[] around and not convert that to a String until you've decrypted the byte array, not a String.

Kayaman
  • 72,141
  • 5
  • 83
  • 121
  • `byte[] c =sgx.jni_sgx_seal_info("encrypt".getBytes(Charset.forName("UTF-8")));` `String unsealed = new String(sgx.jni_sgx_unseal_info(c), StandardCharsets.UTF_8);` `System.out.println(unsealed);` Even by doing it this way, I still receive the `@�)��` output. Could this be due to the choice of data types in c? Does uint8_t affect it? – mute_police Feb 13 '22 at 16:22
  • 1
    I'm having a hard time seeing why `uint8_t` specifically would make it behave that way. You're working with bytes here, whatever you want to call them. – Kayaman Feb 14 '22 at 07:35