hmac.c revision 02c335c23bf5fa225a467c19f2c063fb0dc7b8c3
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz/*
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz * HMAC (RFC-2104) implementation.
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz *
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz * Copyright (c) 2004 Andrey Panin <pazke@donpac.ru>
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen * Copyright (c) 2011-2016 Florian Zeitz <florob@babelmonkeys.de>
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz *
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz * This software is released under the MIT license.
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz */
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz#include "lib.h"
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz#include "hmac.h"
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz#include "safe-memset.h"
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
d8361cc8576d9ede93a037f9b96f2a3f9b7e9054Timo Sirainenvoid hmac_init(struct hmac_context *_ctx, const unsigned char *key,
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz size_t key_len, const struct hash_method *meth)
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz{
d8361cc8576d9ede93a037f9b96f2a3f9b7e9054Timo Sirainen struct hmac_context_priv *ctx = &_ctx->u.priv;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz int i;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz unsigned char k_ipad[64];
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz unsigned char k_opad[64];
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz unsigned char hashedkey[meth->digest_size];
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz i_assert(meth->context_size <= HMAC_MAX_CONTEXT_SIZE);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz ctx->hash = meth;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz if (key_len > 64) {
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->init(ctx->ctx);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->loop(ctx->ctx, key, key_len);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->result(ctx->ctx, hashedkey);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz key = hashedkey;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz key_len = meth->digest_size;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz }
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz memcpy(k_ipad, key, key_len);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz memset(k_ipad + key_len, 0, 64 - key_len);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz memcpy(k_opad, k_ipad, 64);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz for (i = 0; i < 64; i++) {
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz k_ipad[i] ^= 0x36;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz k_opad[i] ^= 0x5c;
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz }
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->init(ctx->ctx);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->loop(ctx->ctx, k_ipad, 64);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->init(ctx->ctxo);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz meth->loop(ctx->ctxo, k_opad, 64);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz safe_memset(k_ipad, 0, 64);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz safe_memset(k_opad, 0, 64);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz}
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
d8361cc8576d9ede93a037f9b96f2a3f9b7e9054Timo Sirainenvoid hmac_final(struct hmac_context *_ctx, unsigned char *digest)
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz{
d8361cc8576d9ede93a037f9b96f2a3f9b7e9054Timo Sirainen struct hmac_context_priv *ctx = &_ctx->u.priv;
d8361cc8576d9ede93a037f9b96f2a3f9b7e9054Timo Sirainen
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz ctx->hash->result(ctx->ctx, digest);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz ctx->hash->loop(ctx->ctxo, digest, ctx->hash->digest_size);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz ctx->hash->result(ctx->ctxo, digest);
0a3769a4ef3afbbbd05df38f43ec7382fd65a2b6Florian Zeitz}