Commit e7ac4efd authored by Pavel Tvrdík's avatar Pavel Tvrdík
Browse files

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

Successfully passed unit tests.
parent b813656c
Loading
Loading
Loading
Loading
+98 −94
Original line number Diff line number Diff line
@@ -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.  */
void
sha256_hmac_init(sha256_hmac_context *ctx, const void *key, size_t keylen)
static void
sha256_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
  sha256_init(&ctx->ctx);
  sha256_context hd_tmp;

  ctx->finalized = 0;
  ctx->use_hmac = 0;
  sha256_init(&hd_tmp);
  sha256_update(&hd_tmp, buffer, length);
  memcpy(outbuf, sha256_final(&hd_tmp), SHA256_SIZE);
}

  if (key)
void
sha256_hmac_init(sha256_hmac_context *ctx, const byte *key, size_t keylen)
{
    int i;
    unsigned char ipad[64];
  byte keybuf[SHA256_BLOCK_SIZE], buf[SHA256_BLOCK_SIZE];

    memset(ipad, 0, 64);
    memset(ctx->opad, 0, 64);
    if (keylen <= 64)
  // Hash the key if necessary
  if (keylen <= SHA256_BLOCK_SIZE)
  {
      memcpy(ipad, key, keylen);
      memcpy(ctx->opad, key, keylen);
    memcpy(keybuf, key, keylen);
    bzero(keybuf + keylen, SHA256_BLOCK_SIZE - keylen);
  }
  else
  {
      sha256_hmac_context tmp_ctx;
    sha256_hash_buffer(keybuf, key, keylen);
    bzero(keybuf + SHA256_SIZE, SHA256_BLOCK_SIZE - SHA256_SIZE);
  }

      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);
  // 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);
}
    for(i=0; i < 64; i++)

void sha256_hmac_update(sha256_hmac_context *ctx, const byte *buf, size_t buflen)
{
      ipad[i] ^= 0x36;
      ctx->opad[i] ^= 0x5c;
    }
    ctx->use_hmac = 1;
    sha256_hmac_update(ctx, ipad, 64);
  }
  // Just update the inner digest
  sha256_update(&ctx->ictx, buf, buflen);
}

void sha224_hmac_init(sha224_hmac_context *ctx, const void *key, size_t keylen)
byte *sha256_hmac_final(sha256_hmac_context *hd)
{
  sha224_init(&ctx->ctx);
  // Finish the inner digest
  byte *isha = sha256_final(&hd->ictx);

  ctx->finalized = 0;
  ctx->use_hmac = 0;
  // Finish the outer digest
  sha256_update(&hd->octx, isha, SHA256_SIZE);
  return sha256_final(&hd->octx);
}

  if (key)
  {
    int i;
    unsigned char ipad[64];
/**
 * 	SHA224-HMAC
 */

    memset(ipad, 0, 64);
    memset(ctx->opad, 0, 64);
    if (keylen <= 64)
static void
sha224_hash_buffer(byte *outbuf, const byte *buffer, size_t length)
{
      memcpy(ipad, key, keylen);
      memcpy(ctx->opad, key, keylen);
  sha224_context hd_tmp;

  sha224_init(&hd_tmp);
  sha224_update(&hd_tmp, buffer, length);
  memcpy(outbuf, sha224_final(&hd_tmp), SHA224_SIZE);
}
    else

void
sha224_hmac_init(sha224_hmac_context *ctx, const byte *key, size_t keylen)
{
      sha224_hmac_context tmp_ctx;
  byte keybuf[SHA224_BLOCK_SIZE], buf[SHA224_BLOCK_SIZE];

      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++)
  // Hash the key if necessary
  if (keylen <= SHA224_BLOCK_SIZE)
  {
      ipad[i] ^= 0x36;
      ctx->opad[i] ^= 0x5c;
    memcpy(keybuf, key, keylen);
    bzero(keybuf + keylen, SHA224_BLOCK_SIZE - keylen);
  }
    ctx->use_hmac = 1;
    sha224_hmac_update(ctx, ipad, 64);
  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);
}

/* 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)
void sha224_hmac_update(sha224_hmac_context *ctx, const byte *buf, size_t buflen)
{
  sha256_update(&ctx->ctx, buffer, length);
  // Just update the inner digest
  sha256_update(&ctx->ictx, buf, buflen);
}

/* 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)
byte *sha224_hmac_final(sha224_hmac_context *hd)
{
  sha256_final(&ctx->ctx);
  if (ctx->use_hmac)
  {
    sha256_hmac_context tmp_ctx;
  // Finish the inner digest
  byte *isha = sha224_final(&hd->ictx);

    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);
  }
  return ctx->ctx.buf;
  // Finish the outer digest
  sha224_update(&hd->octx, isha, SHA224_SIZE);
  return sha224_final(&hd->octx);
}
+14 −20
Original line number Diff line number Diff line
@@ -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_ */

lib/sha256_hmac.h

deleted100644 → 0
+0 −37
Original line number Diff line number Diff line
/*
 *	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_ */
+4 −5
Original line number Diff line number Diff line
@@ -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  = {