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

SHA256: Integrate sha256_hmac into sha256

parent 6d3c17d5
Loading
Loading
Loading
Loading
+101 −19
Original line number Diff line number Diff line
@@ -105,10 +105,13 @@ sum1(u32 x)
      a = t1 + t2;						\
    } while (0)

/*
    The SHA-256 core: Transform the message X which consists of 16
    32-bit-words. See FIPS 180-2 for details.
 */
static unsigned int
transform_blk(void *ctx, const unsigned char *data)
transform(sha256_context *ctx, const unsigned char *data)
{
  sha256_context *hd = ctx;
  static const u32 K[64] = {
      0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
      0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
@@ -132,14 +135,14 @@ transform_blk(void *ctx, const unsigned char *data)
  u32 w[64];
  int i;

  a = hd->h0;
  b = hd->h1;
  c = hd->h2;
  d = hd->h3;
  e = hd->h4;
  f = hd->h5;
  g = hd->h6;
  h = hd->h7;
  a = ctx->h0;
  b = ctx->h1;
  c = ctx->h2;
  d = ctx->h3;
  e = ctx->h4;
  f = ctx->h5;
  g = ctx->h6;
  h = ctx->h7;

  for (i = 0; i < 16; i++)
    w[i] = get_u32(data + i * 4);
@@ -191,14 +194,14 @@ transform_blk(void *ctx, const unsigned char *data)
    i += 8;
  }

  hd->h0 += a;
  hd->h1 += b;
  hd->h2 += c;
  hd->h3 += d;
  hd->h4 += e;
  hd->h5 += f;
  hd->h6 += g;
  hd->h7 += h;
  ctx->h0 += a;
  ctx->h1 += b;
  ctx->h2 += c;
  ctx->h3 += d;
  ctx->h4 += e;
  ctx->h5 += f;
  ctx->h6 += g;
  ctx->h7 += h;

  return /*burn_stack*/ 74*4+32;
}
@@ -214,7 +217,7 @@ sha256_transform(void *ctx, const unsigned char *data, size_t nblks)

  do
  {
    burn = transform_blk(hd, data);
    burn = transform(hd, data);
    data += 64;
  }
  while (--nblks);
@@ -339,3 +342,82 @@ sha256_final(sha256_context *ctx)

  return ctx->buf;
}


/**
 * 	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)
{
  sha256_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
    {
      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);
  }
}

/* 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)
{
  sha256_update(&ctx->ctx, buffer, length);
}

/* 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. */
const byte *
sha256_hmac_final(sha256_hmac_context *ctx)
{
  sha256_final(&ctx->ctx);
  if (ctx->use_hmac)
  {
    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);
  }
  return ctx->ctx.buf;
}
+15 −0
Original line number Diff line number Diff line
@@ -42,4 +42,19 @@ byte* sha224_final(sha224_context *ctx)
  return sha256_final(ctx);
}

/*
 *	HMAC-SHA256
 */
typedef struct
{
  sha256_context ctx;
  int  finalized:1;
  int  use_hmac:1;
  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_H_ */

lib/sha256_hmac.c

deleted100644 → 0
+0 −313
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.
 */

#include "sysdep/config.h"
#include "lib/null.h"
#include "lib/unaligned.h"
#include "lib/sha256_hmac.h"

/* Bitwise rotation of an unsigned int to the right */
static inline u32 ror(u32 x, int n)
{
  return ( (x >> (n&(32-1))) | (x << ((32-n)&(32-1))) );
}

#define my_wipememory2(_ptr,_set,_len) do { \
    volatile char *_vptr=(volatile char *)(_ptr); \
    size_t _vlen=(_len); \
    while(_vlen) { *_vptr=(_set); _vptr++; _vlen--; } \
} while(0)
#define my_wipememory(_ptr,_len) my_wipememory2(_ptr,0,_len)

/*
    The SHA-256 core: Transform the message X which consists of 16
    32-bit-words. See FIPS 180-2 for details.
 */
static void
transform(sha256_hmac_context *hd, const void *data_arg)
{
  const unsigned char *data = data_arg;

#define Cho(x,y,z) (z ^ (x & (y ^ z)))      /* (4.2) same as SHA-1's F1 */
#define Maj(x,y,z) ((x & y) | (z & (x|y)))  /* (4.3) same as SHA-1's F3 */
#define Sum0(x) (ror((x), 2) ^ ror((x), 13) ^ ror((x), 22))  /* (4.4) */
#define Sum1(x) (ror((x), 6) ^ ror((x), 11) ^ ror((x), 25))  /* (4.5) */
#define S0(x) (ror((x), 7) ^ ror((x), 18) ^ ((x) >> 3))       /* (4.6) */
#define S1(x) (ror((x), 17) ^ ror((x), 19) ^ ((x) >> 10))     /* (4.7) */
#define R(a,b,c,d,e,f,g,h,k,w) do                       \
    {                                                   \
  t1 = (h) + Sum1((e)) + Cho((e),(f),(g)) + (k) + (w);  \
  t2 = Sum0((a)) + Maj((a),(b),(c));                    \
  h = g;                                                \
  g = f;                                                \
  f = e;                                                \
  e = d + t1;                                           \
  d = c;                                                \
  c = b;                                                \
  b = a;                                                \
  a = t1 + t2;                                          \
    } while(0)

  static const u32 K[64] =
  {
      0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
      0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
      0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
      0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
      0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
      0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
      0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
      0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
      0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
      0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
      0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
      0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
      0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
      0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
      0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
      0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
  };

  u32 a, b, c, d, e, f, g, h, t1, t2;
  u32 x[16];
  u32 w[64];
  int i;

  a = hd->h0;
  b = hd->h1;
  c = hd->h2;
  d = hd->h3;
  e = hd->h4;
  f = hd->h5;
  g = hd->h6;
  h = hd->h7;

#ifdef WORDS_BIGENDIAN
  memcpy(x, data, 64);
#else /*!WORDS_BIGENDIAN*/
  {
    unsigned char *p2;

    for(i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 )
    {
      p2[3] = *data++;
      p2[2] = *data++;
      p2[1] = *data++;
      p2[0] = *data++;
    }
  }
#endif /*!WORDS_BIGENDIAN*/

  for(i=0; i < 16; i++)
    w[i] = x[i];
  for(; i < 64; i++)
    w[i] = S1(w[i-2]) + w[i-7] + S0(w[i-15]) + w[i-16];

  for(i=0; i < 64; i++)
    R(a,b,c,d,e,f,g,h,K[i],w[i]);

  hd->h0 += a;
  hd->h1 += b;
  hd->h2 += c;
  hd->h3 += d;
  hd->h4 += e;
  hd->h5 += f;
  hd->h6 += g;
  hd->h7 += h;
}
#undef Cho
#undef Maj
#undef Sum0
#undef Sum1
#undef S0
#undef S1
#undef R

/*  Finalize the current SHA256 calculation.  */
static void
finalize(sha256_hmac_context *hd)
{
  u32 t, msb, lsb;
  unsigned char *p;

  if (hd->finalized)
    return; /* Silently ignore a finalized context.  */

  sha256_hmac_update(hd, NULL, 0); /* Flush.  */

  t = hd->nblocks;
  /* Multiply by 64 to make a byte count. */
  lsb = t << 6;
  msb = t >> 26;
  /* Add the count. */
  t = lsb;
  if ((lsb += hd->count) < t)
    msb++;
  /* Multiply by 8 to make a bit count. */
  t = lsb;
  lsb <<= 3;
  msb <<= 3;
  msb |= t >> 29;

  if (hd->count < 56)
  { /* Enough room.  */
    hd->buf[hd->count++] = 0x80; /* pad */
    while(hd->count < 56)
      hd->buf[hd->count++] = 0;  /* pad */
  }
  else
  { /* Need one extra block. */
    hd->buf[hd->count++] = 0x80; /* pad character */
    while(hd->count < 64)
      hd->buf[hd->count++] = 0;
    sha256_hmac_update(hd, NULL, 0);  /* Flush.  */;
    memset(hd->buf, 0, 56 ); /* Zero out next next block.  */
  }
  /* Append the 64 bit count. */
  hd->buf[56] = msb >> 24;
  hd->buf[57] = msb >> 16;
  hd->buf[58] = msb >>  8;
  hd->buf[59] = msb;
  hd->buf[60] = lsb >> 24;
  hd->buf[61] = lsb >> 16;
  hd->buf[62] = lsb >>  8;
  hd->buf[63] = lsb;
  transform(hd, hd->buf);

  /* Store the digest into hd->buf.  */
  p = hd->buf;
#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;	 \
    *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
  X(0);
  X(1);
  X(2);
  X(3);
  X(4);
  X(5);
  X(6);
  X(7);
#undef X
  hd->finalized = 1;
}

/* 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)
{
  ctx->h0 = 0x6a09e667;
  ctx->h1 = 0xbb67ae85;
  ctx->h2 = 0x3c6ef372;
  ctx->h3 = 0xa54ff53a;
  ctx->h4 = 0x510e527f;
  ctx->h5 = 0x9b05688c;
  ctx->h6 = 0x1f83d9ab;
  ctx->h7 = 0x5be0cd19;
  ctx->nblocks = 0;
  ctx->count = 0;
  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
    {
      sha256_hmac_context tmp_ctx;

      sha256_hmac_init(&tmp_ctx, NULL, 0);
      sha256_hmac_update(&tmp_ctx, key, keylen);
      finalize(&tmp_ctx);
      memcpy(ipad, tmp_ctx.buf, 32);
      memcpy(ctx->opad, tmp_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);
    my_wipememory(ipad, 64);
  }
}

/* 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)
{
  const unsigned char *inbuf = buffer;

  if (ctx->finalized)
    return; /* Silently ignore a finalized context.  */

  if (ctx->count == 64)
  {
    /* Flush the buffer. */
    transform(ctx, ctx->buf);
    ctx->count = 0;
    ctx->nblocks++;
  }
  if (!inbuf)
    return;  /* Only flushing was requested. */
  if (ctx->count)
  {
    for(; length && ctx->count < 64; length--)
      ctx->buf[ctx->count++] = *inbuf++;
    sha256_hmac_update(ctx, NULL, 0); /* Flush.  */
    if (!length)
      return;
  }

  while(length >= 64)
  {
    transform(ctx, inbuf);
    ctx->count = 0;
    ctx->nblocks++;
    length -= 64;
    inbuf += 64;
  }
  for(; length && ctx->count < 64; length--)
    ctx->buf[ctx->count++] = *inbuf++;
}

/* 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. */
const byte *
sha256_hmac_final(sha256_hmac_context *ctx)
{
  finalize(ctx);
  if (ctx->use_hmac)
  {
    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->buf, 32);
    finalize(&tmp_ctx);
    memcpy(ctx->buf, tmp_ctx.buf, 32);
  }
  return ctx->buf;
}

lib/sha256_hmac_test.c

deleted100644 → 0
+0 −179
Original line number Diff line number Diff line
/*
 *	BIRD Library -- HMAC-SHA256 Message Authentication Tests
 *
 *	(c) 2015 CZ.NIC z.s.p.o.
 *
 *	Can be freely distributed and used under the terms of the GNU GPL.
 */


#include <stdlib.h>

#include "test/birdtest.h"
#include "sysdep/config.h"
#include "lib/sha256_hmac.h"
#include "lib/sha256_hmac.c"	/* REMOVE ME */

#define HMAC_BUFFER_SIZE 160
struct hmac_data_in {
  byte key[HMAC_BUFFER_SIZE];
  uint key_len;
  byte data[HMAC_BUFFER_SIZE];
  uint data_len;
};

static void
get_sha256_hmac(const struct hmac_data_in in, char (*out_hash)[SHA256_HEX_SIZE])
{
  sha256_hmac_context ctx;
  sha256_hmac_init(&ctx, in.key, in.key_len);
  sha256_hmac_update(&ctx, in.data, in.data_len);
  byte *hash_byte = sha256_hmac_final(&ctx);

  int i;
  for (i = 0; i < SHA256_SIZE; i++)
    sprintf(*out_hash + i*2, "%02x", hash_byte[i]);
}

static int
t_sha256_hmac(void)
{
  struct in_out {
    struct hmac_data_in in;
    char out[SHA256_HEX_SIZE];
  } in_out[] = {
      {
	  .in  = {
	      .key = {
		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
	      },
	      .key_len = 20,
	      .data = "Hi There",
	      .data_len = 8,
	  },
	  .out = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
      },
      {
	  .in  = {
	      .key = "Jefe",
	      .key_len = 4,
	      .data = "what do ya want for nothing?",
	      .data_len = 28,
	  },
	  .out = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
      },
      {
	  .in  = {
	      .key = {
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
	      },
	      .key_len = 20,
	      .data = {
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
	      },
	      .data_len = 50,
	  },
	  .out = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
      },
      {
	  .in  = {
	      .key = {
		  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
		  0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
		  0x15, 0x16, 0x17, 0x18, 0x19,
	      },
	      .key_len = 25,
	      .data = {
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
	      },
	      .data_len = 50,
	  },
	  .out = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
      },
      {
	  .in  = {
	      .key = {
		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
	      },
	      .key_len = 20,
	      .data = "Test With Truncation",
	      .data_len = 20,
	  },
	  .out = "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5",
      },
      {
	  .in  = {
	      .key = {
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa,
	      },
	      .key_len = 131,
	      .data = "Test Using Larger Than Block-Size Key - Hash Key First",
	      .data_len = 54,
	  },
	  .out = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
      },
      {
	  .in  = {
	      .key = {
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa,
	      },
	      .key_len = 131,
	      .data = "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
	      .data_len = 152,
	  },
	  .out = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
      },
  };

  bt_assert_fn_in_out(get_sha256_hmac, in_out, NULL, "'%s'");

  return BT_SUCCESS;
}

int
main(int argc, char *argv[])
{
  bt_init(argc, argv);

  bt_test_suite(t_sha256_hmac, "Test Suite by RFC 4231");
//  bt_test_suite(t_sha224_hmac, "Test Suite by RFC 4231");

  return bt_end();
}
+156 −0
Original line number Diff line number Diff line
@@ -149,6 +149,160 @@ t_sha256_concating(void)
  return BT_SUCCESS;
}


#define HMAC_BUFFER_SIZE 160
struct hmac_data_in {
  byte key[HMAC_BUFFER_SIZE];
  uint key_len;
  byte data[HMAC_BUFFER_SIZE];
  uint data_len;
};

static void
get_sha256_hmac(const struct hmac_data_in in, char (*out_hash)[SHA256_HEX_SIZE])
{
  sha256_hmac_context ctx;
  sha256_hmac_init(&ctx, in.key, in.key_len);
  sha256_hmac_update(&ctx, in.data, in.data_len);
  byte *hash_byte = sha256_hmac_final(&ctx);

  int i;
  for (i = 0; i < SHA256_SIZE; i++)
    sprintf(*out_hash + i*2, "%02x", hash_byte[i]);
}

static int
t_sha256_hmac(void)
{
  struct in_out {
    struct hmac_data_in in;
    char out[SHA256_HEX_SIZE];
  } in_out[] = {
      {
	  .in  = {
	      .key = {
		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
		  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
	      },
	      .key_len = 20,
	      .data = "Hi There",
	      .data_len = 8,
	  },
	  .out = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
      },
      {
	  .in  = {
	      .key = "Jefe",
	      .key_len = 4,
	      .data = "what do ya want for nothing?",
	      .data_len = 28,
	  },
	  .out = "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
      },
      {
	  .in  = {
	      .key = {
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
	      },
	      .key_len = 20,
	      .data = {
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
		  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
	      },
	      .data_len = 50,
	  },
	  .out = "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
      },
      {
	  .in  = {
	      .key = {
		  0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a,
		  0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14,
		  0x15, 0x16, 0x17, 0x18, 0x19,
	      },
	      .key_len = 25,
	      .data = {
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
		  0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd,
	      },
	      .data_len = 50,
	  },
	  .out = "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
      },
      {
	  .in  = {
	      .key = {
		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
		  0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
	      },
	      .key_len = 20,
	      .data = "Test With Truncation",
	      .data_len = 20,
	  },
	  .out = "a3b6167473100ee06e0c796c2955552bfa6f7c0a6a8aef8b93f860aab0cd20c5",
      },
      {
	  .in  = {
	      .key = {
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa,
	      },
	      .key_len = 131,
	      .data = "Test Using Larger Than Block-Size Key - Hash Key First",
	      .data_len = 54,
	  },
	  .out = "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
      },
      {
	  .in  = {
	      .key = {
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
		  0xaa,
	      },
	      .key_len = 131,
	      .data = "This is a test using a larger than block-size key and a larger than block-size data. The key needs to be hashed before being used by the HMAC algorithm.",
	      .data_len = 152,
	  },
	  .out = "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
      },
  };

  bt_assert_fn_in_out(get_sha256_hmac, in_out, NULL, "'%s'");

  return BT_SUCCESS;
}

int
main(int argc, char *argv[])
{
@@ -158,5 +312,7 @@ main(int argc, char *argv[])
  bt_test_suite(t_sha224, "Testing SHA224");
  bt_test_suite(t_sha256_concating, "Testing concating input string to hash process via sha256_update");

  bt_test_suite(t_sha256_hmac, "Test Suite by RFC 4231");

  return bt_end();
}