Provide alternative HMAC interface, with context struct having just derived key and single hash state instead of three hash states at once.
Signed-off-by: Dmitry Eremin-Solenikov dbaryshkov@gmail.com --- hmac.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmac.h | 34 ++++++++++++++++++++++++++++- 2 files changed, 101 insertions(+), 1 deletion(-)
diff --git a/hmac.c b/hmac.c index 6ac5e11a0686..44ac705856ad 100644 --- a/hmac.c +++ b/hmac.c @@ -115,3 +115,71 @@ hmac_digest(const void *outer, const void *inner, void *state,
memcpy(state, inner, hash->context_size); } + +void +hmac2_set_key(void *outer, void *inner, void *state, + const struct nettle_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->init(state); + 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->update(state, key_length, key); + hash->digest(state, 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); + + /* Init happened before */ + hash->update(state, hash->block_size, pad); + memcpy(outer, state, hash->state_size); + + memset(pad, IPAD, hash->block_size); + memxor(pad, key, key_length); + + hash->init(state); + hash->update(state, hash->block_size, pad); + + memcpy(inner, state, hash->state_size); +} + +void +hmac2_update(void *state, + const struct nettle_hash *hash, + size_t length, const uint8_t *data) +{ + hash->update(state, length, data); +} + +void +hmac2_digest(const void *outer, const void *inner, void *state, + const struct nettle_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->digest(state, hash->digest_size, digest); + + memcpy(state, outer, hash->state_size); + + hash->update(state, hash->digest_size, digest); + hash->digest(state, length, dst); + + memcpy(state, inner, hash->state_size); +} diff --git a/hmac.h b/hmac.h index 40a8e77aab6d..e6519023d259 100644 --- a/hmac.h +++ b/hmac.h @@ -49,6 +49,9 @@ extern "C" { #define hmac_set_key nettle_hmac_set_key #define hmac_update nettle_hmac_update #define hmac_digest nettle_hmac_digest +#define hmac2_set_key nettle_hmac2_set_key +#define hmac2_update nettle_hmac2_update +#define hmac2_digest nettle_hmac2_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 @@ -87,6 +90,24 @@ hmac_digest(const void *outer, const void *inner, void *state, size_t length, uint8_t *digest);
+void +hmac2_set_key(void *outer, void *inner, void *state, + const struct nettle_hash *hash, + size_t length, const uint8_t *key); + +/* This function is not strictly needed, it's s just the same as the + * hash update or hmac2_update functions. */ +void +hmac2_update(void *state, + const struct nettle_hash *hash, + size_t length, const uint8_t *data); + +void +hmac2_digest(const void *outer, const void *inner, void *state, + const struct nettle_hash *hash, + size_t length, uint8_t *digest); + + #define HMAC_CTX(type) \ { type outer; type inner; type state; }
@@ -98,10 +119,21 @@ hmac_digest(const void *outer, const void *inner, void *state, hmac_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \ (hash), (length), (digest) )
+#define HMAC2_CTX(ctx_type, type) \ +{ type outer; type inner; ctx_type state; } + +#define HMAC2_SET_KEY(ctx, hash, length, key) \ + hmac2_set_key( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \ + (hash), (length), (key) ) + +#define HMAC2_DIGEST(ctx, hash, length, digest) \ + hmac2_digest( &(ctx)->outer, &(ctx)->inner, &(ctx)->state, \ + (hash), (length), (digest) ) + /* HMAC using specific hash functions */
/* hmac-md5 */ -struct hmac_md5_ctx HMAC_CTX(struct md5_ctx); +struct hmac_md5_ctx HMAC2_CTX(struct md5_ctx, struct md5_state);
void hmac_md5_set_key(struct hmac_md5_ctx *ctx,