I am trying out a small piece of code that would generate HMAC-SHA1. I have been asked to code the HMAC implementation myself using the OpenSSL libs for SHA1 calculation.
After 'wiki'ing for the algorithm, here is what I have below. I have used input with RFC 2104 specified test values:
key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b
key_len = 16 bytes
data = "Hi There"
data_len = 8 bytes digest = 0x9294727a3638bb1c13f48ef8158bfc9d
But the output I get is:
675b0b3a1b4ddf4e124872da6c2f632bfed957e9*
Is this really not the way to implement HMAC? How else can this be done?
#include <openssl/evp.h>
#include <openssl/bn.h>
#include <openssl/sha.h>
#include <openssl/err.h>
#include <openssl/conf.h>
#include <openssl/engine.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for memset() */
#include <unistd.h>
#define IPAD 0x36
#define OPAD 0x5C
#define SHA1_DIGESTLENGTH 20
#define SHA1_BLOCK_LENGTH 64
#define COUNTER_LENGTH 8
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
/**
* Key
*/
#define SECRET { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b , 0x0b , 0x0b , 0x0b , 0x0b , 0x0b , 0x0b , 0x0b , 0x0b}
#define COUNTER { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
/*
* hmac sha1.
*/
int main(int argc, char *argv[]){
unsigned char ipad[SHA1_BLOCK_LENGTH];
unsigned char opad[SHA1_BLOCK_LENGTH];
unsigned char algKey[SHA1_BLOCK_LENGTH];
unsigned char msgBuffer[SHA1_BLOCK_LENGTH + COUNTER_LENGTH];
unsigned char valBuffer[SHA1_BLOCK_LENGTH + 20];
unsigned int i;
uint8_t ctr[] = "Hi There";
uint8_t hash[20];
uint8_t key[]= SECRET;
int len = 16;
memset(hash, 0, sizeof(hash));
memset(algKey, 0, sizeof(algKey));
strncpy((char *)algKey, (char *)key, len);
memset(ipad, IPAD, sizeof(ipad));
memset(opad, OPAD, sizeof(opad));
for (i = 0; i < SHA1_BLOCK_LENGTH; i++){
ipad[i] ^= algKey[i];
}
for (i = 0; i < SHA1_BLOCK_LENGTH; i++){
opad[i] ^= algKey[i];
}
memset(msgBuffer, 0, sizeof(msgBuffer));
strncpy((char *)msgBuffer, (char *)ipad, SHA1_BLOCK_LENGTH);
strncpy((char *)msgBuffer + SHA1_BLOCK_LENGTH, (char *)ctr, COUNTER_LENGTH);
EVP_MD_CTX mdctx, md_ctx;
const EVP_MD *md;
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
OpenSSL_add_all_digests();
md = EVP_get_digestbyname("sha1");
if(!md) {
printf("Unknown message digest\n");
exit(1);
}
EVP_MD_CTX_init(&mdctx);
EVP_DigestInit_ex(&mdctx, md, NULL);
EVP_DigestUpdate(&mdctx, msgBuffer,(SHA1_BLOCK_LENGTH + COUNTER_LENGTH) );
EVP_DigestFinal_ex(&mdctx, md_value, &md_len);
EVP_MD_CTX_cleanup(&mdctx);
printf("Digest is: ");
for(i = 0; i < md_len; i++) printf("%02x", md_value[i]);
printf("\n");
unsigned char *copy;
copy = malloc(md_len);
strncpy((char*)copy, (char *)md_value, md_len);
memset(valBuffer, 0, sizeof(valBuffer));
strncpy((char *)valBuffer, (char *)opad, SHA1_BLOCK_LENGTH);
strncpy((char *)valBuffer + SHA1_BLOCK_LENGTH, (char *)copy, md_len);
EVP_MD_CTX_init(&md_ctx);
EVP_DigestInit_ex(&md_ctx, md, NULL);
EVP_DigestUpdate(&md_ctx, valBuffer, SHA1_BLOCK_LENGTH + 20);
printf( "updated Digest..\n");
EVP_DigestFinal_ex(&md_ctx, md_value, &md_len);
EVP_MD_CTX_cleanup(&md_ctx);
printf("Digest is: ");
for(i = 0; i < md_len; i++) printf("%02x", md_value[i]);
printf("\n");
return 0;
}