0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 02:01:55 +00:00

HMAC-SHA256, HMAC-SHA224 according to HMAC-SHA1

Successfully passed unit tests.
This commit is contained in:
Pavel Tvrdík 2015-04-29 13:39:32 +02:00
parent b813656c58
commit e7ac4efd54
4 changed files with 119 additions and 159 deletions

View File

@ -342,120 +342,124 @@ sha256_final(sha256_context *ctx)
return ctx->buf;
}
/**
* HMAC
* SHA256-HMAC
*/
/* Create a new context. On error NULL is returned and errno is set
appropriately. If KEY is given the function computes HMAC using
this key; with KEY given as NULL, a plain SHA-256 digest is
computed. */
static void
sha256_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
sha256_context hd_tmp;
sha256_init(&hd_tmp);
sha256_update(&hd_tmp, buffer, length);
memcpy(outbuf, sha256_final(&hd_tmp), SHA256_SIZE);
}
void
sha256_hmac_init(sha256_hmac_context *ctx, const void *key, size_t keylen)
sha256_hmac_init(sha256_hmac_context *ctx, const byte *key, size_t keylen)
{
sha256_init(&ctx->ctx);
byte keybuf[SHA256_BLOCK_SIZE], buf[SHA256_BLOCK_SIZE];
ctx->finalized = 0;
ctx->use_hmac = 0;
if (key)
// Hash the key if necessary
if (keylen <= SHA256_BLOCK_SIZE)
{
int i;
unsigned char ipad[64];
memset(ipad, 0, 64);
memset(ctx->opad, 0, 64);
if (keylen <= 64)
{
memcpy(ipad, key, keylen);
memcpy(ctx->opad, key, keylen);
}
else
{
sha256_hmac_context tmp_ctx;
sha256_hmac_init(&tmp_ctx, NULL, 0);
sha256_hmac_update(&tmp_ctx, key, keylen);
sha256_final(&tmp_ctx.ctx);
memcpy(ipad, tmp_ctx.ctx.buf, 32);
memcpy(ctx->opad, tmp_ctx.ctx.buf, 32);
}
for(i=0; i < 64; i++)
{
ipad[i] ^= 0x36;
ctx->opad[i] ^= 0x5c;
}
ctx->use_hmac = 1;
sha256_hmac_update(ctx, ipad, 64);
memcpy(keybuf, key, keylen);
bzero(keybuf + keylen, SHA256_BLOCK_SIZE - keylen);
}
else
{
sha256_hash_buffer(keybuf, key, keylen);
bzero(keybuf + SHA256_SIZE, SHA256_BLOCK_SIZE - SHA256_SIZE);
}
// Initialize the inner digest
sha256_init(&ctx->ictx);
int i;
for (i = 0; i < SHA256_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha256_update(&ctx->ictx, buf, SHA256_BLOCK_SIZE);
// Initialize the outer digest
sha256_init(&ctx->octx);
for (i = 0; i < SHA256_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha256_update(&ctx->octx, buf, SHA256_BLOCK_SIZE);
}
void sha224_hmac_init(sha224_hmac_context *ctx, const void *key, size_t keylen)
void sha256_hmac_update(sha256_hmac_context *ctx, const byte *buf, size_t buflen)
{
sha224_init(&ctx->ctx);
ctx->finalized = 0;
ctx->use_hmac = 0;
if (key)
{
int i;
unsigned char ipad[64];
memset(ipad, 0, 64);
memset(ctx->opad, 0, 64);
if (keylen <= 64)
{
memcpy(ipad, key, keylen);
memcpy(ctx->opad, key, keylen);
}
else
{
sha224_hmac_context tmp_ctx;
sha224_hmac_init(&tmp_ctx, NULL, 0);
sha224_hmac_update(&tmp_ctx, key, keylen);
sha224_final(&tmp_ctx.ctx);
memcpy(ipad, tmp_ctx.ctx.buf, 32);
memcpy(ctx->opad, tmp_ctx.ctx.buf, 32);
}
for(i=0; i < 64; i++)
{
ipad[i] ^= 0x36;
ctx->opad[i] ^= 0x5c;
}
ctx->use_hmac = 1;
sha224_hmac_update(ctx, ipad, 64);
}
// Just update the inner digest
sha256_update(&ctx->ictx, buf, buflen);
}
byte *sha256_hmac_final(sha256_hmac_context *hd)
{
// Finish the inner digest
byte *isha = sha256_final(&hd->ictx);
// Finish the outer digest
sha256_update(&hd->octx, isha, SHA256_SIZE);
return sha256_final(&hd->octx);
}
/**
* SHA224-HMAC
*/
static void
sha224_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
sha224_context hd_tmp;
sha224_init(&hd_tmp);
sha224_update(&hd_tmp, buffer, length);
memcpy(outbuf, sha224_final(&hd_tmp), SHA224_SIZE);
}
/* Update the message digest with the contents of BUFFER containing
LENGTH bytes. */
void
sha256_hmac_update(sha256_hmac_context *ctx, const void *buffer, size_t length)
sha224_hmac_init(sha224_hmac_context *ctx, const byte *key, size_t keylen)
{
sha256_update(&ctx->ctx, buffer, length);
}
byte keybuf[SHA224_BLOCK_SIZE], buf[SHA224_BLOCK_SIZE];
/* Finalize an operation and return the digest. If R_DLEN is not NULL
the length of the digest will be stored at that address. The
returned value is valid as long as the context exists. On error
NULL is returned. */
byte *
sha256_hmac_final(sha256_hmac_context *ctx)
{
sha256_final(&ctx->ctx);
if (ctx->use_hmac)
// Hash the key if necessary
if (keylen <= SHA224_BLOCK_SIZE)
{
sha256_hmac_context tmp_ctx;
sha256_hmac_init(&tmp_ctx, NULL, 0);
sha256_hmac_update(&tmp_ctx, ctx->opad, 64);
sha256_hmac_update(&tmp_ctx, ctx->ctx.buf, 32);
sha256_final(&tmp_ctx.ctx);
memcpy(ctx->ctx.buf, tmp_ctx.ctx.buf, 32);
memcpy(keybuf, key, keylen);
bzero(keybuf + keylen, SHA224_BLOCK_SIZE - keylen);
}
return ctx->ctx.buf;
else
{
sha224_hash_buffer(keybuf, key, keylen);
bzero(keybuf + SHA224_SIZE, SHA224_BLOCK_SIZE - SHA224_SIZE);
}
// Initialize the inner digest
sha224_init(&ctx->ictx);
int i;
for (i = 0; i < SHA224_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x36;
sha224_update(&ctx->ictx, buf, SHA224_BLOCK_SIZE);
// Initialize the outer digest
sha224_init(&ctx->octx);
for (i = 0; i < SHA224_BLOCK_SIZE; i++)
buf[i] = keybuf[i] ^ 0x5c;
sha224_update(&ctx->octx, buf, SHA224_BLOCK_SIZE);
}
void sha224_hmac_update(sha224_hmac_context *ctx, const byte *buf, size_t buflen)
{
// Just update the inner digest
sha256_update(&ctx->ictx, buf, buflen);
}
byte *sha224_hmac_final(sha224_hmac_context *hd)
{
// Finish the inner digest
byte *isha = sha224_final(&hd->ictx);
// Finish the outer digest
sha224_update(&hd->octx, isha, SHA224_SIZE);
return sha224_final(&hd->octx);
}

View File

@ -14,15 +14,17 @@
#include "sysdep/config.h"
#define SHA256_SIZE 32
#define SHA256_HEX_SIZE 65
#define SHA224_SIZE 28
#define SHA224_HEX_SIZE 57
#define SHA224_BLOCK_SIZE 64
#define SHA256_SIZE 32
#define SHA256_HEX_SIZE 65
#define SHA256_BLOCK_SIZE 64
typedef struct {
u32 h0,h1,h2,h3,h4,h5,h6,h7;
byte buf[128];
byte buf[128]; /* 128 is for SHA384 and SHA512 support, otherwise for SHA224 and SHA256 is 64 enough */
u32 nblocks;
u32 nblocks_high;
int count;
@ -46,30 +48,22 @@ byte* sha224_final(sha224_context *ctx)
}
/**
* HMAC-SHA256 & HMAC-SHA224
* HMAC-SHA256, HMAC-SHA224
*/
typedef struct
{
sha256_context ctx;
int finalized:1;
int use_hmac:1;
byte opad[64];
sha256_context ictx;
sha256_context octx;
} sha256_hmac_context;
typedef sha256_hmac_context sha224_hmac_context;
void sha256_hmac_init(sha256_hmac_context *ctx, const void *key, size_t keylen);
void sha224_hmac_init(sha224_hmac_context *ctx, const void *key, size_t keylen);
void sha256_hmac_init(sha256_hmac_context *ctx, const byte *key, size_t keylen);
void sha224_hmac_init(sha224_hmac_context *ctx, const byte *key, size_t keylen);
void sha256_hmac_update(sha256_hmac_context *ctx, const void *buf, size_t buflen);
void sha224_hmac_update(sha224_hmac_context *ctx, const void *buf, size_t buflen)
{
sha256_hmac_update(ctx, buf, buflen);
}
void sha256_hmac_update(sha256_hmac_context *ctx, const byte *buf, size_t buflen);
void sha224_hmac_update(sha224_hmac_context *ctx, const byte *buf, size_t buflen);
byte *sha256_hmac_final(sha256_hmac_context *ctx);
byte *sha224_hmac_final(sha224_hmac_context *ctx)
{
return sha256_hmac_final(ctx);
}
byte *sha224_hmac_final(sha224_hmac_context *ctx);
#endif /* _BIRD_SHA256_H_ */

View File

@ -1,37 +0,0 @@
/*
* BIRD -- HMAC-SHA256 Message Authentication
*
* (c) 2015 CZ.NIC z.s.p.o.
*
* Based on the code from libgcrypt-1.6.0, which is
* (c) 2003, 2006, 2008, 2009 Free Software Foundation, Inc.
*
* Can be freely distributed and used under the terms of the GNU GPL.
*/
#ifndef _BIRD_SHA256_HMAC_H_
#define _BIRD_SHA256_HMAC_H_
#define SHA256_SIZE 32
#define SHA256_HEX_SIZE 65
#define SHA224_SIZE 28
#define SHA224_HEX_SIZE 57
/* The context used by this module. */
typedef struct
{
u32 h0, h1, h2, h3, h4, h5, h6, h7;
u32 nblocks;
int count;
int finalized:1;
int use_hmac:1;
byte buf[64];
byte opad[64];
} sha256_hmac_context;
void sha256_hmac_init(sha256_hmac_context *ctx, const void *key, size_t keylen);
void sha256_hmac_update(sha256_hmac_context *ctx, const void *buf, size_t buflen);
const byte *sha256_hmac_final(sha256_hmac_context *ctx);
#endif /* _BIRD_SHA256_HMAC_H_ */

View File

@ -149,7 +149,6 @@ t_sha256_concating(void)
return BT_SUCCESS;
}
#define HMAC_BUFFER_SIZE 160
struct hmac_data_in {
byte key[HMAC_BUFFER_SIZE];
@ -169,13 +168,13 @@ get_sha256_hmac(const struct hmac_data_in in, char (*out_hash)[SHA256_HEX_SIZE])
}
static void
get_sha224_hmac(const struct hmac_data_in in, char (*out_hash)[SHA256_HEX_SIZE])
get_sha224_hmac(const struct hmac_data_in in, char (*out_hash)[SHA224_HEX_SIZE])
{
sha224_hmac_context ctx;
sha224_hmac_init(&ctx, in.key, in.key_len);
sha224_hmac_update(&ctx, in.data, in.data_len);
byte *hash_byte = sha224_hmac_final(&ctx);
byte_to_hex((char*)out_hash, hash_byte, SHA224_HEX_SIZE);
byte_to_hex((char*)out_hash, hash_byte, SHA224_SIZE);
}
@ -317,7 +316,7 @@ t_sha224_hmac(void)
{
struct in_out {
struct hmac_data_in in;
char out[SHA256_HEX_SIZE];
char out[SHA224_HEX_SIZE];
} in_out[] = {
{
.in = {
@ -387,7 +386,7 @@ t_sha224_hmac(void)
.data = "Test With Truncation",
.data_len = 20,
},
.out = "0e2aea68a90c8d37c988bcdb9fca6fa8",
.out = "0e2aea68a90c8d37c988bcdb9fca6fa8099cd857c7ec4a1815cac54c",
},
{
.in = {