Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Svart_K_
Beginner
111 Views

Calculate HMAC in the enclave

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

0 Kudos
7 Replies
Juan_d_Intel
Employee
111 Views

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.

Svart_K_
Beginner
111 Views

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!?

 

Svart_K_
Beginner
111 Views

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!?

 

Svart_K_
Beginner
111 Views

Can anyone help me with this issue, it's quite urgent!?

 

Thanks

Juan_d_Intel
Employee
111 Views

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

 

Svart_K_
Beginner
111 Views

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

Juan_d_Intel
Employee
111 Views

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