0
0
mirror of https://gitlab.nic.cz/labs/bird.git synced 2024-12-23 18:21:54 +00:00

SHA256: Integrate sha256_hmac into sha256

This commit is contained in:
Pavel Tvrdík 2015-04-28 10:05:25 +02:00
parent 6d3c17d5c2
commit e4e80e4f8f
5 changed files with 272 additions and 511 deletions

View File

@ -105,10 +105,13 @@ sum1(u32 x)
a = t1 + t2; \ a = t1 + t2; \
} while (0) } 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 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] = { static const u32 K[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
@ -132,14 +135,14 @@ transform_blk(void *ctx, const unsigned char *data)
u32 w[64]; u32 w[64];
int i; int i;
a = hd->h0; a = ctx->h0;
b = hd->h1; b = ctx->h1;
c = hd->h2; c = ctx->h2;
d = hd->h3; d = ctx->h3;
e = hd->h4; e = ctx->h4;
f = hd->h5; f = ctx->h5;
g = hd->h6; g = ctx->h6;
h = hd->h7; h = ctx->h7;
for (i = 0; i < 16; i++) for (i = 0; i < 16; i++)
w[i] = get_u32(data + i * 4); w[i] = get_u32(data + i * 4);
@ -191,14 +194,14 @@ transform_blk(void *ctx, const unsigned char *data)
i += 8; i += 8;
} }
hd->h0 += a; ctx->h0 += a;
hd->h1 += b; ctx->h1 += b;
hd->h2 += c; ctx->h2 += c;
hd->h3 += d; ctx->h3 += d;
hd->h4 += e; ctx->h4 += e;
hd->h5 += f; ctx->h5 += f;
hd->h6 += g; ctx->h6 += g;
hd->h7 += h; ctx->h7 += h;
return /*burn_stack*/ 74*4+32; return /*burn_stack*/ 74*4+32;
} }
@ -214,7 +217,7 @@ sha256_transform(void *ctx, const unsigned char *data, size_t nblks)
do do
{ {
burn = transform_blk(hd, data); burn = transform(hd, data);
data += 64; data += 64;
} }
while (--nblks); while (--nblks);
@ -339,3 +342,82 @@ sha256_final(sha256_context *ctx)
return ctx->buf; 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;
}

View File

@ -42,4 +42,19 @@ byte* sha224_final(sha224_context *ctx)
return sha256_final(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_ */ #endif /* _BIRD_SHA256_H_ */

View File

@ -1,313 +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.
*/
#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;
}

View File

@ -1,179 +0,0 @@
/*
* 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();
}

View File

@ -149,6 +149,160 @@ t_sha256_concating(void)
return BT_SUCCESS; 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 int
main(int argc, char *argv[]) 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_sha224, "Testing SHA224");
bt_test_suite(t_sha256_concating, "Testing concating input string to hash process via sha256_update"); 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(); return bt_end();
} }