Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- hmac.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmac.h | 27 +++++++++++++++++++++++++ 2 files changed, 89 insertions(+)
diff --git a/hmac.c b/hmac.c index 6ac5e11a0686..6b925ce6e147 100644 --- a/hmac.c +++ b/hmac.c @@ -115,3 +115,65 @@ hmac_digest(const void *outer, const void *inner, void *state,
memcpy(state, inner, hash->context_size); } + +void +hmac_block_set_key(void *outer, void *inner, void *state, + struct block_ctx *bctx, + const struct nettle_bctx_hash *hash, + size_t key_length, const uint8_t *key) +{ + TMP_DECL(pad, uint8_t, NETTLE_MAX_HASH_BLOCK_SIZE); + TMP_ALLOC(pad, hash->block_size); + + hash->block_init(outer, bctx); + hash->block_init(inner, bctx); + + if (key_length > hash->block_size) + { + /* Reduce key to the algorithm's hash size. Use the area pointed + * to by state for the temporary state. */ + + TMP_DECL(digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE); + TMP_ALLOC(digest, hash->digest_size); + + hash->block_init(state, bctx); + hash->block_update(state, bctx, key_length, key); + hash->block_digest(state, bctx, hash->digest_size, digest); + + key = digest; + key_length = hash->digest_size; + } + + assert(key_length <= hash->block_size); + + memset(pad, OPAD, hash->block_size); + memxor(pad, key, key_length); + + hash->block_update(outer, bctx, hash->block_size, pad); + + memset(pad, IPAD, hash->block_size); + memxor(pad, key, key_length); + + hash->block_update(inner, bctx, hash->block_size, pad); + + memcpy(state, inner, hash->state_size); +} + +void +hmac_block_digest(const void *outer, const void *inner, void *state, + struct block_ctx *bctx, + const struct nettle_bctx_hash *hash, + size_t length, uint8_t *dst) +{ + TMP_DECL(digest, uint8_t, NETTLE_MAX_HASH_DIGEST_SIZE); + TMP_ALLOC(digest, hash->digest_size); + + hash->block_digest(state, bctx, hash->digest_size, digest); + + memcpy(state, outer, hash->state_size); + + hash->block_update(state, bctx, hash->digest_size, digest); + hash->block_digest(state, bctx, length, dst); + + memcpy(state, inner, hash->state_size); +} diff --git a/hmac.h b/hmac.h index 40a8e77aab6d..84ff4a56d93b 100644 --- a/hmac.h +++ b/hmac.h @@ -49,6 +49,8 @@ extern "C" { #define hmac_set_key nettle_hmac_set_key #define hmac_update nettle_hmac_update #define hmac_digest nettle_hmac_digest +#define hmac_block_set_key nettle_hmac_block_set_key +#define hmac_block_digest nettle_hmac_block_digest #define hmac_md5_set_key nettle_hmac_md5_set_key #define hmac_md5_update nettle_hmac_md5_update #define hmac_md5_digest nettle_hmac_md5_digest @@ -86,6 +88,18 @@ hmac_digest(const void *outer, const void *inner, void *state, const struct nettle_hash *hash, size_t length, uint8_t *digest);
+void +hmac_block_set_key(void *outer, void *inner, void *state, + struct block_ctx *bctx, + const struct nettle_bctx_hash *hash, + size_t key_length, const uint8_t *key); + +void +hmac_block_digest(const void *outer, const void *inner, void *state, + struct block_ctx *bctx, + const struct nettle_bctx_hash *hash, + size_t length, uint8_t *digest); +
#define HMAC_CTX(type) \ { type outer; type inner; type state; } @@ -98,6 +112,19 @@ hmac_digest(const void *outer, const void *inner, void *state, hmac_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \ (hash), (length), (digest) )
+#define HMAC_BLOCK_CTX(type, block_size) \ +{ type outer; type inner; type state; BLOCK_CTX(block_size); } + +#define HMAC_BLOCK_SET_KEY(ctx, hash, length, key) \ + hmac_block_set_key( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \ + (struct block_ctx *)&(ctx)->block, \ + (hash), (length), (key) ) + +#define HMAC_BLOCK_DIGEST(ctx, hash, length, digest) \ + hmac_block_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \ + (struct block_ctx *)&(ctx)->block, \ + (hash), (length), (digest) ) + /* HMAC using specific hash functions */
/* hmac-md5 */