Commit ce907a7f authored by Rusty Russell's avatar Rusty Russell

crypto/hmac_sha256: add partial progress functions.

Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent d32033ad
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#define IPAD 0x3636363636363636ULL #define IPAD 0x3636363636363636ULL
#define OPAD 0x5C5C5C5C5C5C5C5CULL #define OPAD 0x5C5C5C5C5C5C5C5CULL
#define BLOCK_U64S (64 / sizeof(uint64_t)) #define BLOCK_U64S (HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t))
static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad) static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad)
{ {
...@@ -15,17 +15,15 @@ static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad) ...@@ -15,17 +15,15 @@ static inline void xor_block(uint64_t block[BLOCK_U64S], uint64_t pad)
block[i] ^= pad; block[i] ^= pad;
} }
#if 1 void hmac_sha256_init(struct hmac_sha256_ctx *ctx,
void hmac_sha256(struct hmac_sha256 *hmac, const void *k, size_t ksize)
const void *k, size_t ksize,
const void *d, size_t dsize)
{ {
struct sha256_ctx shactx; struct sha256 hashed_key;
uint64_t block[BLOCK_U64S]; /* We use k_opad as k_ipad temporarily. */
struct sha256 hash, hashed_key; uint64_t *k_ipad = ctx->k_opad;
/* (keys longer than B bytes are first hashed using H) */ /* (keys longer than B bytes are first hashed using H) */
if (ksize > sizeof(block)) { if (ksize > HMAC_SHA256_BLOCKSIZE) {
sha256(&hashed_key, k, ksize); sha256(&hashed_key, k, ksize);
k = &hashed_key; k = &hashed_key;
ksize = sizeof(hashed_key); ksize = sizeof(hashed_key);
...@@ -37,30 +35,48 @@ void hmac_sha256(struct hmac_sha256 *hmac, ...@@ -37,30 +35,48 @@ void hmac_sha256(struct hmac_sha256 *hmac,
* (e.g., if K is of length 20 bytes and B=64, then K will be * (e.g., if K is of length 20 bytes and B=64, then K will be
* appended with 44 zero bytes 0x00) * appended with 44 zero bytes 0x00)
*/ */
memcpy(block, k, ksize); memcpy(k_ipad, k, ksize);
memset((char *)block + ksize, 0, sizeof(block) - ksize); memset((char *)k_ipad + ksize, 0, HMAC_SHA256_BLOCKSIZE - ksize);
/* /*
* (2) XOR (bitwise exclusive-OR) the B byte string computed * (2) XOR (bitwise exclusive-OR) the B byte string computed
* in step (1) with ipad * in step (1) with ipad
*/ */
xor_block(block, IPAD); xor_block(k_ipad, IPAD);
/* /*
* We start (4) here, appending text later:
*
* (3) append the stream of data 'text' to the B byte string resulting * (3) append the stream of data 'text' to the B byte string resulting
* from step (2) * from step (2)
* (4) apply H to the stream generated in step (3) * (4) apply H to the stream generated in step (3)
*/ */
sha256_init(&shactx); sha256_init(&ctx->sha);
sha256_update(&shactx, block, sizeof(block)); sha256_update(&ctx->sha, k_ipad, HMAC_SHA256_BLOCKSIZE);
sha256_update(&shactx, d, dsize);
sha256_done(&shactx, &hash);
/* /*
* (5) XOR (bitwise exclusive-OR) the B byte string computed in * (5) XOR (bitwise exclusive-OR) the B byte string computed in
* step (1) with opad * step (1) with opad
*/ */
xor_block(block, IPAD^OPAD); xor_block(ctx->k_opad, IPAD^OPAD);
}
void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size)
{
/* This is the appending-text part of this:
*
* (3) append the stream of data 'text' to the B byte string resulting
* from step (2)
* (4) apply H to the stream generated in step (3)
*/
sha256_update(&ctx->sha, p, size);
}
void hmac_sha256_done(struct hmac_sha256_ctx *ctx,
struct hmac_sha256 *hmac)
{
/* (4) apply H to the stream generated in step (3) */
sha256_done(&ctx->sha, &hmac->sha);
/* /*
* (6) append the H result from step (4) to the B byte string * (6) append the H result from step (4) to the B byte string
...@@ -68,10 +84,22 @@ void hmac_sha256(struct hmac_sha256 *hmac, ...@@ -68,10 +84,22 @@ void hmac_sha256(struct hmac_sha256 *hmac,
* (7) apply H to the stream generated in step (6) and output * (7) apply H to the stream generated in step (6) and output
* the result * the result
*/ */
sha256_init(&shactx); sha256_init(&ctx->sha);
sha256_update(&shactx, block, sizeof(block)); sha256_update(&ctx->sha, ctx->k_opad, sizeof(ctx->k_opad));
sha256_update(&shactx, &hash, sizeof(hash)); sha256_update(&ctx->sha, &hmac->sha, sizeof(hmac->sha));
sha256_done(&shactx, &hmac->sha); sha256_done(&ctx->sha, &hmac->sha);
}
#if 1
void hmac_sha256(struct hmac_sha256 *hmac,
const void *k, size_t ksize,
const void *d, size_t dsize)
{
struct hmac_sha256_ctx ctx;
hmac_sha256_init(&ctx, k, ksize);
hmac_sha256_update(&ctx, d, dsize);
hmac_sha256_done(&ctx, hmac);
} }
#else #else
/* Direct mapping from MD5 example in RFC2104 */ /* Direct mapping from MD5 example in RFC2104 */
......
...@@ -6,12 +6,8 @@ ...@@ -6,12 +6,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <ccan/crypto/sha256/sha256.h> #include <ccan/crypto/sha256/sha256.h>
/* Uncomment this to use openssl's HMAC routines (and link with -lcrypto) */ /* Number of bytes per block. */
/*#define CCAN_CRYPTO_HMAC_USE_OPENSSL 1*/ #define HMAC_SHA256_BLOCKSIZE 64
#ifdef CCAN_CRYPTO_HMAC_USE_OPENSSL
#include <openssl/hmac.h>
#endif
/** /**
* struct hmac_sha256 - structure representing a completed HMAC. * struct hmac_sha256 - structure representing a completed HMAC.
...@@ -31,4 +27,60 @@ struct hmac_sha256 { ...@@ -31,4 +27,60 @@ struct hmac_sha256 {
void hmac_sha256(struct hmac_sha256 *hmac, void hmac_sha256(struct hmac_sha256 *hmac,
const void *k, size_t ksize, const void *k, size_t ksize,
const void *d, size_t dsize); const void *d, size_t dsize);
/**
* struct hmac_sha256_ctx - structure to store running context for hmac_sha256
*/
struct hmac_sha256_ctx {
struct sha256_ctx sha;
uint64_t k_opad[HMAC_SHA256_BLOCKSIZE / sizeof(uint64_t)];
};
/**
* hmac_sha256_init - initialize an HMAC_SHA256 context.
* @ctx: the hmac_sha256_ctx to initialize
* @k: pointer to the key,
* @ksize: the number of bytes pointed to by @k
*
* This must be called before hmac_sha256_update or hmac_sha256_done.
*
* If it was already initialized, this forgets anything which was
* hashed before.
*
* Example:
* static void hmac_all(const char *key,
* const char **arr, struct hmac_sha256 *hash)
* {
* size_t i;
* struct hmac_sha256_ctx ctx;
*
* hmac_sha256_init(&ctx, key, strlen(key));
* for (i = 0; arr[i]; i++)
* hmac_sha256_update(&ctx, arr[i], strlen(arr[i]));
* hmac_sha256_done(&ctx, hash);
* }
*/
void hmac_sha256_init(struct hmac_sha256_ctx *ctx,
const void *k, size_t ksize);
/**
* hmac_sha256_update - include some memory in the hash.
* @ctx: the hmac_sha256_ctx to use
* @p: pointer to memory,
* @size: the number of bytes pointed to by @p
*
* You can call this multiple times to hash more data, before calling
* hmac_sha256_done().
*/
void hmac_sha256_update(struct hmac_sha256_ctx *ctx, const void *p, size_t size);
/**
* hmac_sha256_done - finish HMAC_SHA256 and return the hash
* @ctx: the hmac_sha256_ctx to complete
* @res: the hash to return.
*
* Note that @ctx is *destroyed* by this, and must be reinitialized.
* To avoid that, pass a copy instead.
*/
void hmac_sha256_done(struct hmac_sha256_ctx *hmac_sha256, struct hmac_sha256 *res);
#endif /* CCAN_CRYPTO_HMAC_SHA256_H */ #endif /* CCAN_CRYPTO_HMAC_SHA256_H */
...@@ -129,11 +129,12 @@ int main(void) ...@@ -129,11 +129,12 @@ int main(void)
size_t i; size_t i;
struct hmac_sha256 hmac; struct hmac_sha256 hmac;
plan_tests(sizeof(tests) / sizeof(tests[0])); plan_tests(sizeof(tests) / sizeof(tests[0]) * 2);
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) {
size_t ksize, dsize, hmacsize; size_t ksize, dsize, hmacsize;
void *k, *d, *expect; void *k, *d, *expect;
struct hmac_sha256_ctx ctx;
k = fromhex(tests[i].key, &ksize); k = fromhex(tests[i].key, &ksize);
d = fromhex(tests[i].data, &dsize); d = fromhex(tests[i].data, &dsize);
...@@ -141,6 +142,14 @@ int main(void) ...@@ -141,6 +142,14 @@ int main(void)
assert(hmacsize == sizeof(hmac)); assert(hmacsize == sizeof(hmac));
hmac_sha256(&hmac, k, ksize, d, dsize); hmac_sha256(&hmac, k, ksize, d, dsize);
ok1(memcmp(&hmac, expect, hmacsize) == 0); ok1(memcmp(&hmac, expect, hmacsize) == 0);
/* Now test partial API. */
hmac_sha256_init(&ctx, k, ksize);
hmac_sha256_update(&ctx, d, dsize / 2);
hmac_sha256_update(&ctx, (char *)d + dsize/2, dsize - dsize/2);
hmac_sha256_done(&ctx, &hmac);
ok1(memcmp(&hmac, expect, hmacsize) == 0);
free(k); free(k);
free(d); free(d);
free(expect); free(expect);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment