Hi,
is there a predefined function that can be used inside the enclave to calculate a HMAC with SHA512?
If not is there a proper "workaround" or alternative?
Thanks
Link Copied
The SGX SDK exposes the IPP crypto API.
You may include the IPP crypto header files in your enclave project to access the Keyed Hash API.
A description of the relevant IPP Crypto API is posted here: https://software.intel.com/en-us/node/503181
HMAC with SHA512 is supported. You only need to pass the appropriate hash algorithm (IppHashAlgId = SHA-512) to the HMAC_Init call.
Hi,
thanks for the reply!
I managed to call the "ippsHMAC_GetSize" and "ippsHMAC_Init" functions successfully, but now I'm lost with the "HMAC_Update" one!?
Is there any example available!?
Okay I got it to work now with two different variants. The problem is when testing it with a predefined key and message, the returned hmac is different each time!?
This is the method that with the two variants:
int calculateHMAC(uint8_t *key, uint8_t *nonce, uint8_t *res_hmac) { IppsHMACState *ctx; IppStatus status; int psize = 0; //VARIANT 1 status = ippsHMAC_GetSize(&psize); if (status == ippStsNullPtrErr) return 1; ctx = (IppsHMACState*) malloc(psize); status = ippsHMAC_Init(key, HMAC_KEY_LENGTH, ctx, ippHashAlg_SHA512); if (status != ippStsNoErr) return 1; status = ippsHMAC_Update(nonce, HMAC_NONCE_LENGTH, ctx); if (status != ippStsNoErr) return 1; uint8_t hmac[HMAC_LENGTH]; memset(hmac, '\0', HMAC_LENGTH); status = ippsHMAC_Final(hmac, HMAC_LENGTH, ctx); if (status != ippStsNoErr) return 1; status = ippsHMAC_GetTag(hmac, HMAC_LENGTH, ctx); if (status != ippStsNoErr) return 1; memcpy(res_hmac, hmac, HMAC_LENGTH); //VARIANT 2 // uint8_t test_hmac[HMAC_LENGTH]; // status = ippsHMAC_Message(nonce, HMAC_NONCE_LENGTH, key, HMAC_KEY_LENGTH, test_hmac, HMAC_LENGTH, ippHashAlg_SHA512); // if (status != ippStsNoErr) // return 1; // memcpy(res_hmac, test_hmac, HMAC_LENGTH); return 0; }
This is a static example, that should when being executed result in the same hmac on each call:
char nonce[] = "7d93099f7fed16215836f7bad4db0e48"; char key[] = "a5b115536d5bf350c5b0fa6f69242f18"; uint8_t t_hmac[64]; memset(t_hmac, '\0', 64); uint8_t ba_nonce[16]; int count = 0; for (unsigned int i=0; i<32; i+=2) { char tmp[2]; tmp[0] = nonce; tmp[1] = nonce[i+1]; char byte = (char) strtol(tmp, NULL, 16); ba_nonce[count] = (unsigned char)byte; count++; } uint8_t ba_key[16]; count = 0; for (unsigned int i=0; i<32; i+=2) { char tmp[2]; tmp[0] = key; tmp[1] = key[i+1]; char byte = (char) strtol(tmp, NULL, 16); ba_key[count] = (unsigned char)byte; count++; } int error = calculateHMAC(ba_key, ba_nonce, t_hmac);
The t_hmac variable contains the calculated HMAC, but is not the same for multiple executions!?
Can anyone help me with this issue, it's quite urgent!?
Thanks
The code above seems okay, except that you should only call ippsHMAC_GetTag to determine the current value of the message digest between the two calls to ippsHMAC_Update.
Are you sure the values of HMAC_KEY_LENGTH, HMAC_NONCE_LENGTH, and HMAC_LENGTH are correct? If you specify a larger buffer size you'd be operating on undefined data, hence the different HMAC values.
In case, it helps, this is what my enclave is producing:
KEY (16): a5b115536d5bf350c5b0fa6f69242f18 NONCE (16): 7d93099f7fed1621583676bad4db0e48 HMAC (64): 50b628bc940ac4ce5729a416320870094723d62e3e0d043c87e441547dea5934abcb74da488b49392d99c1bd5d8a8e8d94d6ce8acd9f3cd1dceb179fa6dc1349
Alright I've removed the ippsHMAC_GetTag call now to this:
int calculateHMAC(uint8_t *key, uint8_t *nonce, uint8_t *res_hmac) { IppsHMACState *ctx; IppStatus status; int psize = 0; //VARIANT 1 status = ippsHMAC_GetSize(&psize); if (status == ippStsNullPtrErr) return 1; ctx = (IppsHMACState*) malloc(psize); status = ippsHMAC_Init(key, 16, ctx, ippHashAlg_SHA512); if (status != ippStsNoErr) return 1; status = ippsHMAC_Update(nonce, 16, ctx); if (status != ippStsNoErr) return 1; uint8_t hmac[HMAC_LENGTH]; memset(hmac, '\0', HMAC_LENGTH); status = ippsHMAC_Final(hmac, HMAC_LENGTH, ctx); if (status != ippStsNoErr) return 1; memcpy(res_hmac, hmac, HMAC_LENGTH); }
And the call is the same:
char nonce[] = "7d93099f7fed16215836f7bad4db0e48"; char key[] = "a5b115536d5bf350c5b0fa6f69242f18"; uint8_t t_hmac[64]; memset(t_hmac, '\0', 64); uint8_t ba_nonce[16]; int count = 0; for (unsigned int i=0; i<32; i+=2) { char tmp[2]; tmp[0] = nonce; tmp[1] = nonce[i+1]; char byte = (char) strtol(tmp, NULL, 16); ba_nonce[count] = (unsigned char)byte; count++; } uint8_t ba_key[16]; count = 0; for (unsigned int i=0; i<32; i+=2) { char tmp[2]; tmp[0] = key; tmp[1] = key[i+1]; char byte = (char) strtol(tmp, NULL, 16); ba_key[count] = (unsigned char)byte; count++; } int error = calculateHMAC(ba_key, ba_nonce, t_hmac); mbedtls_printf("Key: "); for(int i = 0; i < 16; i++) mbedtls_printf("%02x", (unsigned int)ba_key); mbedtls_printf("\n"); mbedtls_printf("Nonce: "); for(int i = 0; i < 16; i++) mbedtls_printf("%02x", (unsigned int)ba_nonce); mbedtls_printf("\n"); mbedtls_printf("HMAC: "); for(int i = 0; i < 64; i++) mbedtls_printf("%02x", (unsigned int)t_hmac); mbedtls_printf("\n");
For which I receive the output:
Key: a5b115536d5bf350c5b0fa6f69242f18
Nonce: 7d93099f7fed16215836f7bad4db0e48
HMAC: 7d2f2e3d57c84a58945b9016fb37e2df03afdde313c9d79c31ec1e6612d6d6b20456a8fcf799ef74d16f60c7f283e621400004422885f33fb3d2bb7ae7a1daa3
But this is not the correct HMAC-SHA512 and neither is yours, since according to this tool http://beautifytools.com/hmac-generator.php
the result should be:
dd8406481da579254295ee9ea9632bd6cb80b56116b1b93207b1caa3245c0cbbbdf4b3ebcc0d1c4e85ff55fbdd2a65eca25f48b641a1a9bc0e6442467bd8ce79
This tools takes your data and key as ASCII strings. Make one of the hex letters uppercase and the result will change.
Your program takes the input as binary representation.
I realized that the program does not terminate "tmp" properly. As a result, depending on what's in the stack strtol may not return what you'd expect. When I ran the original program, the nonce was translated into something slightly different, see below.
Originally: 7d93099f7fed16215836f7bad4db0e48
I was using: 7d93099f7fed1621583676bad4db0e48
After changing the conversion routine, I got the same HMAC as you.
KEY (16): a5b115536d5bf350c5b0fa6f69242f18 NONCE (16): 7d93099f7fed16215836f7bad4db0e48 HMAC (64): 7d2f2e3d57c84a58945b9016fb37e2df03afdde313c9d79c31ec1e6612d6d6b20456a8fcf799ef74d16f60c7f283e621400004422885f33fb3d2bb7ae7a1daa3
For more complete information about compiler optimizations, see our Optimization Notice.