Day: November 7, 2022

Compiling a simples HMAC MD5 test

I was trying do some tests with HMAC:

#include <stdint.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <openssl/hmac.h>
#include <openssl/ossl_typ.h>

static int openssl_hmac_vector(const EVP_MD *type, const uint8_t *key,
			       size_t key_len, size_t num_elem,
			       const uint8_t *addr[], const size_t *len, uint8_t *mac,
			       unsigned int mdlen)
{
	HMAC_CTX *ctx;
	size_t i;
	int res;

	ctx = HMAC_CTX_new();
#if OPENSSL_VERSION_NUMBER < 0x00909000
	HMAC_Init_ex(ctx, key, key_len, type, NULL);
#else /* openssl < 0.9.9 */
	if (HMAC_Init_ex(ctx, key, key_len, type, NULL) != 1)
		return -1;
#endif /* openssl < 0.9.9 */

	for (i = 0; i < num_elem; i++)
		HMAC_Update(ctx, addr[i], len[i]);

#if OPENSSL_VERSION_NUMBER < 0x00909000
	HMAC_Final(ctx, mac, &mdlen);
	res = 1;
#else /* openssl < 0.9.9 */
	res = HMAC_Final(ctx, mac, &mdlen);
#endif /* openssl < 0.9.9 */
	HMAC_CTX_free(ctx);

	return res == 1 ? 0 : -1;
}

int hmac_md5_vector(const uint8_t *key, size_t key_len, size_t num_elem,
		    const uint8_t *addr[], const size_t *len, uint8_t *mac)
{
	return openssl_hmac_vector(EVP_md5(), key ,key_len, num_elem, addr, len,
				   mac, 16);
}

int hmac_md5(const uint8_t *key, size_t key_len, const uint8_t *data, size_t data_len,
	     uint8_t *mac)
{
	return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
}

int main(void)
{
  int i;
  uint8_t key[8] = {'S', '3', 'c', 'r', 'e', 't', 's', '!'};
  const uint8_t msg[16] = {'M', 'y', ' ', 'M', 'e', 's', 's', 'a', 'g', 'e', ' ', 'p', 'l', 'a', 'i', 'n'};
  uint8_t hmac[128];

  memset(hmac, 0x00, 128);

  hmac_md5(key, 8, msg, 16, hmac);

  for (i = 0; i < 16; i++)
    {
      printf("hmac[%d] = %02X\n", i, hmac[i]);
    }

  return 0;
}

But it was failing to compile:

$ gcc testhmac.c -o testhmac
/usr/bin/ld: /tmp/cczEFXg9.o: in function `openssl_hmac_vector':
testhmac.c:(.text+0x25): undefined reference to `HMAC_CTX_new'
/usr/bin/ld: testhmac.c:(.text+0x4e): undefined reference to `HMAC_Init_ex'
/usr/bin/ld: testhmac.c:(.text+0xa2): undefined reference to `HMAC_Update'
/usr/bin/ld: testhmac.c:(.text+0xc5): undefined reference to `HMAC_Final'
/usr/bin/ld: testhmac.c:(.text+0xd4): undefined reference to `HMAC_CTX_free'
/usr/bin/ld: /tmp/cczEFXg9.o: in function `hmac_md5_vector':
testhmac.c:(.text+0x111): undefined reference to `EVP_md5'
collect2: error: ld returned 1 exit status

Passing -lssl didn’t solve the issue:

$ gcc testhmac.c -o testhmac -lssl
/usr/bin/ld: /tmp/ccRUYEU0.o: in function `openssl_hmac_vector':
testhmac.c:(.text+0x25): undefined reference to `HMAC_CTX_new'
/usr/bin/ld: testhmac.c:(.text+0x4e): undefined reference to `HMAC_Init_ex'
/usr/bin/ld: testhmac.c:(.text+0xa2): undefined reference to `HMAC_Update'
/usr/bin/ld: testhmac.c:(.text+0xc5): undefined reference to `HMAC_Final'
/usr/bin/ld: testhmac.c:(.text+0xd4): undefined reference to `HMAC_CTX_free'
/usr/bin/ld: /tmp/ccRUYEU0.o: in function `hmac_md5_vector':
testhmac.c:(.text+0x111): undefined reference to `EVP_md5'
collect2: error: ld returned 1 exit status

You need to use -lcrypto (some people suggest -lssl -lcrypto)

$ gcc testhmac.c -o testhmac -lcrypto

Now it compiled fine and I can run it:

$ ./testhmac 
hmac[0] = 3D
hmac[1] = 32
hmac[2] = 76
hmac[3] = FD
hmac[4] = E3
hmac[5] = FB
hmac[6] = 42
hmac[7] = D8
hmac[8] = F0
hmac[9] = 05
hmac[10] = 53
hmac[11] = CC
hmac[12] = 12
hmac[13] = E7
hmac[14] = C9
hmac[15] = C3