Simplify hmac implementations

This commit is contained in:
Jonathan Bennett 2016-01-02 21:59:26 -06:00
parent a3e0d1cc1b
commit af7d9e8544

View File

@ -32,45 +32,6 @@
#ifdef HAVE_C_UNIT_TESTS
DECLARE_TEST_SUITE(hmac_test, "hmac functions test suite");
#endif
typedef struct {
MD5Context ctx_inside;
MD5Context ctx_outside;
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
} hmac_md5_ctx;
typedef struct {
SHA1_INFO ctx_inside;
SHA1_INFO ctx_outside;
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
} hmac_sha1_ctx;
typedef struct {
SHA256_CTX ctx_inside;
SHA256_CTX ctx_outside;
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
} hmac_sha256_ctx;
typedef struct {
SHA384_CTX ctx_inside;
SHA384_CTX ctx_outside;
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
} hmac_sha384_ctx;
typedef struct {
SHA512_CTX ctx_inside;
SHA512_CTX ctx_outside;
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN];
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN];
} hmac_sha512_ctx;
static void
pad_init(unsigned char *inner_pad, unsigned char *outer_pad,
@ -97,351 +58,226 @@ pad_init(unsigned char *inner_pad, unsigned char *outer_pad,
/* Begin MD5 HMAC functions
*/
static void
hmac_md5_init(hmac_md5_ctx *ctx, const char *key, const int key_len)
{
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char init_key[MAX_DIGEST_BLOCK_LEN] = {0};
int final_len = key_len;
if(key_len > MAX_DIGEST_BLOCK_LEN)
final_len = MAX_DIGEST_BLOCK_LEN;
memcpy(init_key, key, final_len);
if(MD5_BLOCK_LEN < key_len)
{
/* Calculate the digest of the key
*/
md5(final_key, init_key, final_len);
}
else
{
memcpy(final_key, init_key, key_len);
}
pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
MD5Init(&ctx->ctx_inside);
MD5Update(&ctx->ctx_inside, ctx->block_inner_pad, MD5_BLOCK_LEN);
MD5Init(&ctx->ctx_outside);
MD5Update(&ctx->ctx_outside, ctx->block_outer_pad, MD5_BLOCK_LEN);
return;
}
static void
hmac_md5_update(hmac_md5_ctx *ctx, const char *msg,
unsigned int msg_len)
{
MD5Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
return;
}
static void
hmac_md5_final(hmac_md5_ctx *ctx, unsigned char *hmac)
{
unsigned char digest_inside[MD5_DIGEST_LEN];
MD5Final(digest_inside, &ctx->ctx_inside);
MD5Update(&ctx->ctx_outside, digest_inside, MD5_DIGEST_LEN);
MD5Final(hmac, &ctx->ctx_outside);
return;
}
void
hmac_md5(const char *msg, const unsigned int msg_len,
unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
{
hmac_md5_ctx ctx;
unsigned char inner_hash[MD5_DIGEST_LEN] = {0};
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char padded_hash[MD5_BLOCK_LEN + MD5_DIGEST_LEN + 1] = {0};
unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1);
memset(&ctx, 0, sizeof(ctx));
int final_len = hmac_key_len;
hmac_md5_init(&ctx, hmac_key, hmac_key_len);
hmac_md5_update(&ctx, msg, msg_len);
hmac_md5_final(&ctx, hmac);
if(MD5_BLOCK_LEN < hmac_key_len)
{
/* Calculate the digest of the key
*/
md5(final_key, (unsigned char *)hmac_key, final_len);
final_len = MD5_DIGEST_LEN;
}
else
{
memcpy(final_key, hmac_key, hmac_key_len);
}
pad_init(block_inner_pad, block_outer_pad, final_key, final_len);
//The first step is to hash the inner_pad + message
memcpy(padded_msg, block_inner_pad, MD5_BLOCK_LEN);
memcpy(padded_msg + MD5_BLOCK_LEN, msg, msg_len);
//Calculate the inner hash
md5(inner_hash, padded_msg, msg_len + MD5_BLOCK_LEN);
//Then hash the outer pad + inner hash
memcpy(padded_hash, block_outer_pad, MD5_BLOCK_LEN);
memcpy(padded_hash + MD5_BLOCK_LEN, inner_hash, MD5_DIGEST_LEN);
//the outer hash is the final hmac
md5(hmac, padded_hash, MD5_BLOCK_LEN + MD5_DIGEST_LEN);
free(padded_msg);
return;
}
/* Begin SHA1 HMAC functions
*/
static void
hmac_sha1_init(hmac_sha1_ctx *ctx, const char *key, const int key_len)
{
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char init_key[MAX_DIGEST_BLOCK_LEN] = {0};
int final_len = key_len;
if(key_len > MAX_DIGEST_BLOCK_LEN)
final_len = MAX_DIGEST_BLOCK_LEN;
memcpy(init_key, key, final_len);
if(SHA1_BLOCK_LEN < key_len)
{
/* Calculate the digest of the key
*/
sha1(final_key, init_key, final_len);
}
else
{
memcpy(final_key, init_key, key_len);
}
pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
sha1_init(&ctx->ctx_inside);
sha1_update(&ctx->ctx_inside, ctx->block_inner_pad, SHA1_BLOCK_LEN);
sha1_init(&ctx->ctx_outside);
sha1_update(&ctx->ctx_outside, ctx->block_outer_pad, SHA1_BLOCK_LEN);
return;
}
static void
hmac_sha1_update(hmac_sha1_ctx *ctx, const char *msg,
unsigned int msg_len)
{
sha1_update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
return;
}
static void
hmac_sha1_final(hmac_sha1_ctx *ctx, unsigned char *hmac)
{
unsigned char digest_inside[SHA1_DIGEST_LEN];
sha1_final(digest_inside, &ctx->ctx_inside);
sha1_update(&ctx->ctx_outside, digest_inside, SHA1_DIGEST_LEN);
sha1_final(hmac, &ctx->ctx_outside);
return;
}
void
hmac_sha1(const char *msg, const unsigned int msg_len,
unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
{
hmac_sha1_ctx ctx;
unsigned char inner_hash[SHA1_DIGEST_LEN] = {0};
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char padded_hash[SHA1_BLOCK_LEN + SHA1_DIGEST_LEN + 1] = {0};
unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1);
memset(&ctx, 0, sizeof(ctx));
int final_len = hmac_key_len;
hmac_sha1_init(&ctx, hmac_key, hmac_key_len);
hmac_sha1_update(&ctx, msg, msg_len);
hmac_sha1_final(&ctx, hmac);
if(SHA1_BLOCK_LEN < hmac_key_len)
{
/* Calculate the digest of the key
*/
sha1(final_key, (unsigned char *)hmac_key, final_len);
final_len = SHA1_DIGEST_LEN;
}
else
{
memcpy(final_key, hmac_key, hmac_key_len);
}
pad_init(block_inner_pad, block_outer_pad, final_key, final_len);
//The first step is to hash the inner_pad + message
memcpy(padded_msg, block_inner_pad, SHA1_BLOCK_LEN);
memcpy(padded_msg + SHA1_BLOCK_LEN, msg, msg_len);
//Calculate the inner hash
sha1(inner_hash, padded_msg, msg_len + SHA1_BLOCK_LEN);
//Then hash the outer pad + inner hash
memcpy(padded_hash, block_outer_pad, SHA1_BLOCK_LEN);
memcpy(padded_hash + SHA1_BLOCK_LEN, inner_hash, SHA1_DIGEST_LEN);
//the outer hash is the final hmac
sha1(hmac, padded_hash, SHA1_BLOCK_LEN + SHA1_DIGEST_LEN);
free(padded_msg);
return;
}
/* Begin SHA256 HMAC functions
*/
static void
hmac_sha256_init(hmac_sha256_ctx *ctx, const char *key, const int key_len)
{
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char init_key[MAX_DIGEST_BLOCK_LEN] = {0};
int final_len = key_len;
if(key_len > MAX_DIGEST_BLOCK_LEN)
final_len = MAX_DIGEST_BLOCK_LEN;
memcpy(init_key, key, final_len);
if(SHA256_BLOCK_LEN < key_len)
{
/* Calculate the digest of the key
*/
sha256(final_key, init_key, final_len);
}
else
{
memcpy(final_key, init_key, key_len);
}
pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
SHA256_Init(&ctx->ctx_inside);
SHA256_Update(&ctx->ctx_inside, ctx->block_inner_pad, SHA256_BLOCK_LEN);
SHA256_Init(&ctx->ctx_outside);
SHA256_Update(&ctx->ctx_outside, ctx->block_outer_pad, SHA256_BLOCK_LEN);
return;
}
static void
hmac_sha256_update(hmac_sha256_ctx *ctx, const char *msg,
unsigned int msg_len)
{
SHA256_Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
return;
}
static void
hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *hmac)
{
unsigned char digest_inside[SHA256_DIGEST_LEN];
SHA256_Final(digest_inside, &ctx->ctx_inside);
SHA256_Update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_LEN);
SHA256_Final(hmac, &ctx->ctx_outside);
return;
}
void
hmac_sha256(const char *msg, const unsigned int msg_len,
unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
{
hmac_sha256_ctx ctx;
unsigned char inner_hash[SHA256_DIGEST_LEN] = {0};
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char padded_hash[SHA256_BLOCK_LEN + SHA256_DIGEST_LEN + 1] = {0};
unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1);
memset(&ctx, 0, sizeof(ctx));
int final_len = hmac_key_len;
hmac_sha256_init(&ctx, hmac_key, hmac_key_len);
hmac_sha256_update(&ctx, msg, msg_len);
hmac_sha256_final(&ctx, hmac);
if(SHA256_BLOCK_LEN < hmac_key_len)
{
/* Calculate the digest of the key
*/
sha256(final_key, (unsigned char *)hmac_key, final_len);
final_len = SHA256_DIGEST_LEN;
}
else
{
memcpy(final_key, hmac_key, hmac_key_len);
}
pad_init(block_inner_pad, block_outer_pad, final_key, final_len);
//The first step is to hash the inner_pad + message
memcpy(padded_msg, block_inner_pad, SHA256_BLOCK_LEN);
memcpy(padded_msg + SHA256_BLOCK_LEN, msg, msg_len);
//Calculate the inner hash
sha256(inner_hash, padded_msg, msg_len + SHA256_BLOCK_LEN);
//Then hash the outer pad + inner hash
memcpy(padded_hash, block_outer_pad, SHA256_BLOCK_LEN);
memcpy(padded_hash + SHA256_BLOCK_LEN, inner_hash, SHA256_DIGEST_LEN);
//the outer hash is the final hmac
sha256(hmac, padded_hash, SHA256_BLOCK_LEN + SHA256_DIGEST_LEN);
free(padded_msg);
return;
}
/* Begin SHA384 HMAC functions
*/
static void
hmac_sha384_init(hmac_sha384_ctx *ctx, const char *key, const int key_len)
{
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
int final_len = key_len;
if(key_len > MAX_DIGEST_BLOCK_LEN)
final_len = MAX_DIGEST_BLOCK_LEN;
if(SHA384_BLOCK_LEN < key_len)
{
/* Calculate the digest of the key
*/
sha384(final_key, (unsigned char *)key, final_len);
}
else
{
memcpy(final_key, key, key_len);
}
pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
SHA384_Init(&ctx->ctx_inside);
SHA384_Update(&ctx->ctx_inside, ctx->block_inner_pad, SHA384_BLOCK_LEN);
SHA384_Init(&ctx->ctx_outside);
SHA384_Update(&ctx->ctx_outside, ctx->block_outer_pad, SHA384_BLOCK_LEN);
return;
}
static void
hmac_sha384_update(hmac_sha384_ctx *ctx, const char *msg,
unsigned int msg_len)
{
SHA384_Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
return;
}
static void
hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *hmac)
{
unsigned char digest_inside[SHA384_DIGEST_LEN];
SHA384_Final(digest_inside, &ctx->ctx_inside);
SHA384_Update(&ctx->ctx_outside, digest_inside, SHA384_DIGEST_LEN);
SHA384_Final(hmac, &ctx->ctx_outside);
return;
}
void
hmac_sha384(const char *msg, const unsigned int msg_len,
unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
{
hmac_sha384_ctx ctx;
unsigned char inner_hash[SHA384_DIGEST_LEN] = {0};
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char padded_hash[SHA384_BLOCK_LEN + SHA384_DIGEST_LEN + 1] = {0};
unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1);
memset(&ctx, 0, sizeof(ctx));
int final_len = hmac_key_len;
hmac_sha384_init(&ctx, hmac_key, hmac_key_len);
hmac_sha384_update(&ctx, msg, msg_len);
hmac_sha384_final(&ctx, hmac);
if(SHA384_BLOCK_LEN < hmac_key_len)
{
/* Calculate the digest of the key
*/
sha384(final_key, (unsigned char *)hmac_key, final_len);
final_len = SHA384_DIGEST_LEN;
}
else
{
memcpy(final_key, hmac_key, hmac_key_len);
}
pad_init(block_inner_pad, block_outer_pad, final_key, final_len);
//The first step is to hash the inner_pad + message
memcpy(padded_msg, block_inner_pad, SHA384_BLOCK_LEN);
memcpy(padded_msg + SHA384_BLOCK_LEN, msg, msg_len);
//Calculate the inner hash
sha384(inner_hash, padded_msg, msg_len + SHA384_BLOCK_LEN);
//Then hash the outer pad + inner hash
memcpy(padded_hash, block_outer_pad, SHA384_BLOCK_LEN);
memcpy(padded_hash + SHA384_BLOCK_LEN, inner_hash, SHA384_DIGEST_LEN);
//the outer hash is the final hmac
sha384(hmac, padded_hash, SHA384_BLOCK_LEN + SHA384_DIGEST_LEN);
free(padded_msg);
return;
}
/* Begin SHA512 HMAC functions
*/
static void
hmac_sha512_init(hmac_sha512_ctx *ctx, const char *key, const int key_len)
{
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
int final_len = key_len;
if(key_len > MAX_DIGEST_BLOCK_LEN)
final_len = MAX_DIGEST_BLOCK_LEN;
if(SHA512_BLOCK_LEN < key_len)
{
/* Calculate the digest of the key
*/
sha512(final_key, (unsigned char *)key, final_len);
final_len = SHA512_DIGEST_LEN;
}
else
{
memcpy(final_key, key, key_len);
}
pad_init(ctx->block_inner_pad, ctx->block_outer_pad, final_key, final_len);
SHA512_Init(&ctx->ctx_inside);
SHA512_Update(&ctx->ctx_inside, ctx->block_inner_pad, SHA512_BLOCK_LEN);
SHA512_Init(&ctx->ctx_outside);
SHA512_Update(&ctx->ctx_outside, ctx->block_outer_pad, SHA512_BLOCK_LEN);
return;
}
static void
hmac_sha512_update(hmac_sha512_ctx *ctx, const char *msg,
unsigned int msg_len)
{
SHA512_Update(&ctx->ctx_inside, (unsigned char *)msg, msg_len);
return;
}
static void
hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *hmac)
{
unsigned char digest_inside[SHA512_DIGEST_LEN];
SHA512_Final(digest_inside, &ctx->ctx_inside);
SHA512_Update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_LEN);
SHA512_Final(hmac, &ctx->ctx_outside);
return;
}
void
hmac_sha512(const char *msg, const unsigned int msg_len,
unsigned char *hmac, const char *hmac_key, const int hmac_key_len)
{
hmac_sha512_ctx ctx;
unsigned char inner_hash[SHA512_DIGEST_LEN] = {0};
unsigned char block_inner_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char block_outer_pad[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char final_key[MAX_DIGEST_BLOCK_LEN] = {0};
unsigned char padded_hash[SHA512_BLOCK_LEN + SHA512_DIGEST_LEN + 1] = {0};
unsigned char *padded_msg = malloc(msg_len + MAX_DIGEST_BLOCK_LEN + 1);
memset(&ctx, 0, sizeof(ctx));
int final_len = hmac_key_len;
hmac_sha512_init(&ctx, hmac_key, hmac_key_len);
hmac_sha512_update(&ctx, msg, msg_len);
hmac_sha512_final(&ctx, hmac);
if(SHA512_BLOCK_LEN < hmac_key_len)
{
/* Calculate the digest of the key
*/
sha512(final_key, (unsigned char *)hmac_key, final_len);
final_len = SHA512_DIGEST_LEN;
}
else
{
memcpy(final_key, hmac_key, hmac_key_len);
}
pad_init(block_inner_pad, block_outer_pad, final_key, final_len);
//The first step is to hash the inner_pad + message
memcpy(padded_msg, block_inner_pad, SHA512_BLOCK_LEN);
memcpy(padded_msg + SHA512_BLOCK_LEN, msg, msg_len);
//Calculate the inner hash
sha512(inner_hash, padded_msg, msg_len + SHA512_BLOCK_LEN);
//Then hash the outer pad + inner hash
memcpy(padded_hash, block_outer_pad, SHA512_BLOCK_LEN);
memcpy(padded_hash + SHA512_BLOCK_LEN, inner_hash, SHA512_DIGEST_LEN);
//the outer hash is the final hmac
sha512(hmac, padded_hash, SHA512_BLOCK_LEN + SHA512_DIGEST_LEN);
free(padded_msg);
return;
}