[Dovecot] [PATCH] Generalize HMAC implementation
Florian Zeitz
florob at babelmonkeys.de
Tue Sep 4 21:25:54 EEST 2012
Hello everyone and Timo in particular,
about a year ago I implemented a SHA-1 variant of the HMAC(-MD5) present
in Dovecot.
I had always disliked this a bit, because it replicates a lot of code.
This patch generalizes the HMAC function to take a hash_method struct as
parameter, and changes existing code which uses the "old" HMAC function
to use this new one.
I'm not really sure this is actually a good idea, but I still felt I
should provide the code in case you would want to merge it upstream.
Attached is the patch as a hg export based on the revision of
dovecot-2.2 current at the time of writing.
Regards,
Florian Zeitz
-------------- next part --------------
# HG changeset patch
# User Florian Zeitz <florob at babelmonkeys.de>
# Date 1346280236 -7200
# Node ID e2f682fab829c2ef23a050f884191f57e2fb5d60
# Parent 9bc2e718392ceaa327f14b50163232b629cd54d1
lib: Generalize hmac to be hash independent
diff --git a/src/auth/mech-cram-md5.c b/src/auth/mech-cram-md5.c
--- a/src/auth/mech-cram-md5.c
+++ b/src/auth/mech-cram-md5.c
@@ -7,7 +7,9 @@
#include "ioloop.h"
#include "buffer.h"
#include "hex-binary.h"
-#include "hmac-md5.h"
+#include "hmac-cram-md5.h"
+#include "hmac.h"
+#include "md5.h"
#include "randgen.h"
#include "mech.h"
#include "passdb.h"
@@ -50,7 +52,7 @@
{
unsigned char digest[MD5_RESULTLEN];
- struct hmac_md5_context ctx;
+ struct hmac_context ctx;
const char *response_hex;
if (size != CRAM_MD5_CONTEXTLEN) {
@@ -59,9 +61,10 @@
return FALSE;
}
+ hmac_init(&ctx, NULL, 0, &hash_method_md5);
hmac_md5_set_cram_context(&ctx, credentials);
- hmac_md5_update(&ctx, request->challenge, strlen(request->challenge));
- hmac_md5_final(&ctx, digest);
+ hmac_update(&ctx, request->challenge, strlen(request->challenge));
+ hmac_final(&ctx, digest);
response_hex = binary_to_hex(digest, sizeof(digest));
diff --git a/src/auth/mech-scram-sha1.c b/src/auth/mech-scram-sha1.c
--- a/src/auth/mech-scram-sha1.c
+++ b/src/auth/mech-scram-sha1.c
@@ -9,7 +9,8 @@
#include "auth-common.h"
#include "base64.h"
#include "buffer.h"
-#include "hmac-sha1.h"
+#include "hmac.h"
+#include "sha1.h"
#include "randgen.h"
#include "safe-memset.h"
#include "str.h"
@@ -44,23 +45,23 @@
const unsigned char *salt, size_t salt_size, unsigned int i,
unsigned char result[SHA1_RESULTLEN])
{
- struct hmac_sha1_context ctx;
+ struct hmac_context ctx;
unsigned char U[SHA1_RESULTLEN];
unsigned int j, k;
/* Calculate U1 */
- hmac_sha1_init(&ctx, str, str_size);
- hmac_sha1_update(&ctx, salt, salt_size);
- hmac_sha1_update(&ctx, "\0\0\0\1", 4);
- hmac_sha1_final(&ctx, U);
+ hmac_init(&ctx, str, str_size, &hash_method_sha1);
+ hmac_update(&ctx, salt, salt_size);
+ hmac_update(&ctx, "\0\0\0\1", 4);
+ hmac_final(&ctx, U);
memcpy(result, U, SHA1_RESULTLEN);
/* Calculate U2 to Ui and Hi */
for (j = 2; j <= i; j++) {
- hmac_sha1_init(&ctx, str, str_size);
- hmac_sha1_update(&ctx, U, sizeof(U));
- hmac_sha1_final(&ctx, U);
+ hmac_init(&ctx, str, str_size, &hash_method_sha1);
+ hmac_update(&ctx, U, sizeof(U));
+ hmac_final(&ctx, U);
for (k = 0; k < SHA1_RESULTLEN; k++)
result[k] ^= U[k];
}
@@ -94,7 +95,7 @@
static const char *get_scram_server_final(struct scram_auth_request *request)
{
- struct hmac_sha1_context ctx;
+ struct hmac_context ctx;
const char *auth_message;
unsigned char server_key[SHA1_RESULTLEN];
unsigned char server_signature[SHA1_RESULTLEN];
@@ -104,17 +105,17 @@
request->server_first_message, ",",
request->client_final_message_without_proof, NULL);
- hmac_sha1_init(&ctx, request->salted_password,
- sizeof(request->salted_password));
- hmac_sha1_update(&ctx, "Server Key", 10);
- hmac_sha1_final(&ctx, server_key);
+ hmac_init(&ctx, request->salted_password,
+ sizeof(request->salted_password), &hash_method_sha1);
+ hmac_update(&ctx, "Server Key", 10);
+ hmac_final(&ctx, server_key);
safe_memset(request->salted_password, 0,
sizeof(request->salted_password));
- hmac_sha1_init(&ctx, server_key, sizeof(server_key));
- hmac_sha1_update(&ctx, auth_message, strlen(auth_message));
- hmac_sha1_final(&ctx, server_signature);
+ hmac_init(&ctx, server_key, sizeof(server_key), &hash_method_sha1);
+ hmac_update(&ctx, auth_message, strlen(auth_message));
+ hmac_final(&ctx, server_signature);
str = t_str_new(MAX_BASE64_ENCODED_SIZE(sizeof(server_signature)));
str_append(str, "v=");
@@ -213,7 +214,7 @@
static bool verify_credentials(struct scram_auth_request *request,
const unsigned char *credentials, size_t size)
{
- struct hmac_sha1_context ctx;
+ struct hmac_context ctx;
const char *auth_message;
unsigned char client_key[SHA1_RESULTLEN];
unsigned char client_signature[SHA1_RESULTLEN];
@@ -224,10 +225,10 @@
Hi(credentials, size, request->salt, sizeof(request->salt),
SCRAM_ITERATE_COUNT, request->salted_password);
- hmac_sha1_init(&ctx, request->salted_password,
- sizeof(request->salted_password));
- hmac_sha1_update(&ctx, "Client Key", 10);
- hmac_sha1_final(&ctx, client_key);
+ hmac_init(&ctx, request->salted_password,
+ sizeof(request->salted_password), &hash_method_sha1);
+ hmac_update(&ctx, "Client Key", 10);
+ hmac_final(&ctx, client_key);
sha1_get_digest(client_key, sizeof(client_key), stored_key);
@@ -235,9 +236,9 @@
request->server_first_message, ",",
request->client_final_message_without_proof, NULL);
- hmac_sha1_init(&ctx, stored_key, sizeof(stored_key));
- hmac_sha1_update(&ctx, auth_message, strlen(auth_message));
- hmac_sha1_final(&ctx, client_signature);
+ hmac_init(&ctx, stored_key, sizeof(stored_key), &hash_method_sha1);
+ hmac_update(&ctx, auth_message, strlen(auth_message));
+ hmac_final(&ctx, client_signature);
for (i = 0; i < sizeof(client_signature); i++)
client_signature[i] ^= client_key[i];
diff --git a/src/auth/password-scheme.c b/src/auth/password-scheme.c
--- a/src/auth/password-scheme.c
+++ b/src/auth/password-scheme.c
@@ -6,7 +6,8 @@
#include "hex-binary.h"
#include "md4.h"
#include "md5.h"
-#include "hmac-md5.h"
+#include "hmac.h"
+#include "hmac-cram-md5.h"
#include "ntlm.h"
#include "mycrypt.h"
#include "randgen.h"
@@ -655,12 +656,12 @@
cram_md5_generate(const char *plaintext, const char *user ATTR_UNUSED,
const unsigned char **raw_password_r, size_t *size_r)
{
- struct hmac_md5_context ctx;
+ struct hmac_context ctx;
unsigned char *context_digest;
context_digest = t_malloc(CRAM_MD5_CONTEXTLEN);
- hmac_md5_init(&ctx, (const unsigned char *)plaintext,
- strlen(plaintext));
+ hmac_init(&ctx, (const unsigned char *)plaintext,
+ strlen(plaintext), &hash_method_md5);
hmac_md5_get_cram_context(&ctx, context_digest);
*raw_password_r = context_digest;
diff --git a/src/lib-ntlm/ntlm-encrypt.c b/src/lib-ntlm/ntlm-encrypt.c
--- a/src/lib-ntlm/ntlm-encrypt.c
+++ b/src/lib-ntlm/ntlm-encrypt.c
@@ -11,7 +11,8 @@
#include "compat.h"
#include "safe-memset.h"
#include "md4.h"
-#include "hmac-md5.h"
+#include "md5.h"
+#include "hmac.h"
#include "ntlm.h"
#include "ntlm-des.h"
@@ -60,12 +61,12 @@
}
static void
-hmac_md5_ucs2le_string_ucase(struct hmac_md5_context *ctx, const char *str)
+hmac_md5_ucs2le_string_ucase(struct hmac_context *ctx, const char *str)
{
size_t len;
unsigned char *wstr = t_unicode_str(str, 1, &len);
- hmac_md5_update(ctx, wstr, len);
+ hmac_update(ctx, wstr, len);
}
static void ATTR_NULL(2)
@@ -73,13 +74,13 @@
const unsigned char *hash_v1,
unsigned char hash[NTLMSSP_V2_HASH_SIZE])
{
- struct hmac_md5_context ctx;
+ struct hmac_context ctx;
- hmac_md5_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE);
+ hmac_init(&ctx, hash_v1, NTLMSSP_HASH_SIZE, &hash_method_md5);
hmac_md5_ucs2le_string_ucase(&ctx, user);
if (target != NULL)
hmac_md5_ucs2le_string_ucase(&ctx, target);
- hmac_md5_final(&ctx, hash);
+ hmac_final(&ctx, hash);
}
void
@@ -124,15 +125,15 @@
const unsigned char *blob, size_t blob_size,
unsigned char response[NTLMSSP_V2_RESPONSE_SIZE])
{
- struct hmac_md5_context ctx;
+ struct hmac_context ctx;
unsigned char hash[NTLMSSP_V2_HASH_SIZE];
ntlm_v2_hash(user, target, hash_v1, hash);
- hmac_md5_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE);
- hmac_md5_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE);
- hmac_md5_update(&ctx, blob, blob_size);
- hmac_md5_final(&ctx, response);
+ hmac_init(&ctx, hash, NTLMSSP_V2_HASH_SIZE, &hash_method_md5);
+ hmac_update(&ctx, challenge, NTLMSSP_CHALLENGE_SIZE);
+ hmac_update(&ctx, blob, blob_size);
+ hmac_final(&ctx, response);
safe_memset(hash, 0, sizeof(hash));
}
diff --git a/src/lib/Makefile.am b/src/lib/Makefile.am
--- a/src/lib/Makefile.am
+++ b/src/lib/Makefile.am
@@ -44,8 +44,8 @@
hash2.c \
hex-binary.c \
hex-dec.c \
- hmac-md5.c \
- hmac-sha1.c \
+ hmac.c \
+ hmac-cram-md5.c \
home-expand.c \
hostpid.c \
imem.c \
@@ -170,8 +170,8 @@
hash2.h \
hex-binary.h \
hex-dec.h \
- hmac-md5.h \
- hmac-sha1.h \
+ hmac.h \
+ hmac-cram-md5.h \
home-expand.h \
hostpid.h \
imem.h \
diff --git a/src/lib/hmac-cram-md5.c b/src/lib/hmac-cram-md5.c
new file mode 100644
--- /dev/null
+++ b/src/lib/hmac-cram-md5.c
@@ -0,0 +1,64 @@
+/*
+ * CRAM-MD5 (RFC 2195) compatibility code
+ * Copyright (c) 2003 Joshua Goodall <joshua at roughtrade.net>
+ *
+ * This software is released under the MIT license.
+ */
+
+#include "lib.h"
+#include "md5.h"
+#include "hmac.h"
+#include "hmac-cram-md5.h"
+
+void hmac_md5_get_cram_context(struct hmac_context *hmac_ctx,
+ unsigned char context_digest[CRAM_MD5_CONTEXTLEN])
+{
+ unsigned char *cdp;
+
+ struct md5_context *ctx = hmac_ctx->ctx;
+ struct md5_context *ctxo = hmac_ctx->ctxo;
+
+#define CDPUT(p, c) STMT_START { \
+ *(p)++ = (c) & 0xff; \
+ *(p)++ = (c) >> 8 & 0xff; \
+ *(p)++ = (c) >> 16 & 0xff; \
+ *(p)++ = (c) >> 24 & 0xff; \
+} STMT_END
+ cdp = context_digest;
+ CDPUT(cdp, ctxo->a);
+ CDPUT(cdp, ctxo->b);
+ CDPUT(cdp, ctxo->c);
+ CDPUT(cdp, ctxo->d);
+ CDPUT(cdp, ctx->a);
+ CDPUT(cdp, ctx->b);
+ CDPUT(cdp, ctx->c);
+ CDPUT(cdp, ctx->d);
+}
+
+void hmac_md5_set_cram_context(struct hmac_context *hmac_ctx,
+ const unsigned char context_digest[CRAM_MD5_CONTEXTLEN])
+{
+ const unsigned char *cdp;
+
+ struct md5_context *ctx = hmac_ctx->ctx;
+ struct md5_context *ctxo = hmac_ctx->ctxo;
+
+#define CDGET(p, c) STMT_START { \
+ (c) = (*p++); \
+ (c) += (*p++ << 8); \
+ (c) += (*p++ << 16); \
+ (c) += (*p++ << 24); \
+} STMT_END
+ cdp = context_digest;
+ CDGET(cdp, ctxo->a);
+ CDGET(cdp, ctxo->b);
+ CDGET(cdp, ctxo->c);
+ CDGET(cdp, ctxo->d);
+ CDGET(cdp, ctx->a);
+ CDGET(cdp, ctx->b);
+ CDGET(cdp, ctx->c);
+ CDGET(cdp, ctx->d);
+
+ ctxo->lo = ctx->lo = 64;
+ ctxo->hi = ctx->hi = 0;
+}
diff --git a/src/lib/hmac-cram-md5.h b/src/lib/hmac-cram-md5.h
new file mode 100644
--- /dev/null
+++ b/src/lib/hmac-cram-md5.h
@@ -0,0 +1,12 @@
+#ifndef HMAC_CRAM_MD5_H
+#define HMAC_CRAM_MD5_H
+
+#define CRAM_MD5_CONTEXTLEN 32
+
+void hmac_md5_get_cram_context(struct hmac_context *ctx,
+ unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
+void hmac_md5_set_cram_context(struct hmac_context *ctx,
+ const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
+
+
+#endif
diff --git a/src/lib/hmac-md5.c b/src/lib/hmac-md5.c
deleted file mode 100644
--- a/src/lib/hmac-md5.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * HMAC-MD5 (RFC-2104) implementation.
- *
- * Copyright (c) 2004 Andrey Panin <pazke at donpac.ru>
- *
- * CRAM-MD5 (RFC 2195) compatibility code
- * Copyright (c) 2003 Joshua Goodall <joshua at roughtrade.net>
- *
- * This software is released under the MIT license.
- */
-
-#include "lib.h"
-#include "hmac-md5.h"
-#include "safe-memset.h"
-
-void hmac_md5_init(struct hmac_md5_context *ctx,
- const unsigned char *key, size_t key_len)
-{
- int i;
- unsigned char md5key[16];
- unsigned char k_ipad[64];
- unsigned char k_opad[64];
-
- if (key_len > 64) {
- md5_get_digest(key, key_len, md5key);
- key = md5key;
- key_len = 16;
- }
-
- memcpy(k_ipad, key, key_len);
- memset(k_ipad + key_len, 0, 64 - key_len);
- memcpy(k_opad, k_ipad, 64);
-
- for (i = 0; i < 64; i++) {
- k_ipad[i] ^= 0x36;
- k_opad[i] ^= 0x5c;
- }
-
- md5_init(&ctx->ctx);
- md5_update(&ctx->ctx, k_ipad, 64);
- md5_init(&ctx->ctxo);
- md5_update(&ctx->ctxo, k_opad, 64);
-
- safe_memset(k_ipad, 0, 64);
- safe_memset(k_opad, 0, 64);
-}
-
-void hmac_md5_final(struct hmac_md5_context *ctx, unsigned char *digest)
-{
- md5_final(&ctx->ctx, digest);
-
- md5_update(&ctx->ctxo, digest, 16);
- md5_final(&ctx->ctxo, digest);
-}
-
-void hmac_md5_get_cram_context(struct hmac_md5_context *ctx,
- unsigned char context_digest[CRAM_MD5_CONTEXTLEN])
-{
- unsigned char *cdp;
-
-#define CDPUT(p, c) STMT_START { \
- *(p)++ = (c) & 0xff; \
- *(p)++ = (c) >> 8 & 0xff; \
- *(p)++ = (c) >> 16 & 0xff; \
- *(p)++ = (c) >> 24 & 0xff; \
-} STMT_END
- cdp = context_digest;
- CDPUT(cdp, ctx->ctxo.a);
- CDPUT(cdp, ctx->ctxo.b);
- CDPUT(cdp, ctx->ctxo.c);
- CDPUT(cdp, ctx->ctxo.d);
- CDPUT(cdp, ctx->ctx.a);
- CDPUT(cdp, ctx->ctx.b);
- CDPUT(cdp, ctx->ctx.c);
- CDPUT(cdp, ctx->ctx.d);
-}
-
-void hmac_md5_set_cram_context(struct hmac_md5_context *ctx,
- const unsigned char context_digest[CRAM_MD5_CONTEXTLEN])
-{
- const unsigned char *cdp;
-
-#define CDGET(p, c) STMT_START { \
- (c) = (*p++); \
- (c) += (*p++ << 8); \
- (c) += (*p++ << 16); \
- (c) += (*p++ << 24); \
-} STMT_END
- cdp = context_digest;
- CDGET(cdp, ctx->ctxo.a);
- CDGET(cdp, ctx->ctxo.b);
- CDGET(cdp, ctx->ctxo.c);
- CDGET(cdp, ctx->ctxo.d);
- CDGET(cdp, ctx->ctx.a);
- CDGET(cdp, ctx->ctx.b);
- CDGET(cdp, ctx->ctx.c);
- CDGET(cdp, ctx->ctx.d);
-
- ctx->ctxo.lo = ctx->ctx.lo = 64;
- ctx->ctxo.hi = ctx->ctx.hi = 0;
-}
diff --git a/src/lib/hmac-md5.h b/src/lib/hmac-md5.h
deleted file mode 100644
--- a/src/lib/hmac-md5.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef HMAC_MD5_H
-#define HMAC_MD5_H
-
-#include "md5.h"
-
-#define CRAM_MD5_CONTEXTLEN 32
-
-struct hmac_md5_context {
- struct md5_context ctx, ctxo;
-};
-
-void hmac_md5_init(struct hmac_md5_context *ctx,
- const unsigned char *key, size_t key_len);
-void hmac_md5_final(struct hmac_md5_context *ctx,
- unsigned char digest[MD5_RESULTLEN]);
-
-void hmac_md5_get_cram_context(struct hmac_md5_context *ctx,
- unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
-void hmac_md5_set_cram_context(struct hmac_md5_context *ctx,
- const unsigned char context_digest[CRAM_MD5_CONTEXTLEN]);
-
-
-static inline void
-hmac_md5_update(struct hmac_md5_context *ctx, const void *data, size_t size)
-{
- md5_update(&ctx->ctx, data, size);
-}
-
-#endif
diff --git a/src/lib/hmac-sha1.c b/src/lib/hmac-sha1.c
deleted file mode 100644
--- a/src/lib/hmac-sha1.c
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * HMAC-SHA1 (RFC-2104) implementation.
- *
- * Copyright (c) 2004 Andrey Panin <pazke at donpac.ru>
- * Copyright (c) 2011 Florian Zeitz <florob at babelmonkeys.de>
- *
- * This software is released under the MIT license.
- */
-
-#include "lib.h"
-#include "hmac-sha1.h"
-#include "safe-memset.h"
-
-void hmac_sha1_init(struct hmac_sha1_context *ctx,
- const unsigned char *key, size_t key_len)
-{
- int i;
- unsigned char sha1key[20];
- unsigned char k_ipad[64];
- unsigned char k_opad[64];
-
- if (key_len > 64) {
- sha1_get_digest(key, key_len, sha1key);
- key = sha1key;
- key_len = 20;
- }
-
- memcpy(k_ipad, key, key_len);
- memset(k_ipad + key_len, 0, 64 - key_len);
- memcpy(k_opad, k_ipad, 64);
-
- for (i = 0; i < 64; i++) {
- k_ipad[i] ^= 0x36;
- k_opad[i] ^= 0x5c;
- }
-
- sha1_init(&ctx->ctx);
- sha1_loop(&ctx->ctx, k_ipad, 64);
- sha1_init(&ctx->ctxo);
- sha1_loop(&ctx->ctxo, k_opad, 64);
-
- safe_memset(k_ipad, 0, 64);
- safe_memset(k_opad, 0, 64);
-}
-
-void hmac_sha1_final(struct hmac_sha1_context *ctx, unsigned char *digest)
-{
- sha1_result(&ctx->ctx, digest);
-
- sha1_loop(&ctx->ctxo, digest, 20);
- sha1_result(&ctx->ctxo, digest);
-}
diff --git a/src/lib/hmac-sha1.h b/src/lib/hmac-sha1.h
deleted file mode 100644
--- a/src/lib/hmac-sha1.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef HMAC_SHA1_H
-#define HMAC_SHA1_H
-
-#include "sha1.h"
-
-struct hmac_sha1_context {
- struct sha1_ctxt ctx, ctxo;
-};
-
-void hmac_sha1_init(struct hmac_sha1_context *ctx,
- const unsigned char *key, size_t key_len);
-void hmac_sha1_final(struct hmac_sha1_context *ctx,
- unsigned char digest[SHA1_RESULTLEN]);
-
-
-static inline void
-hmac_sha1_update(struct hmac_sha1_context *ctx, const void *data, size_t size)
-{
- sha1_loop(&ctx->ctx, data, size);
-}
-
-#endif
diff --git a/src/lib/hmac.c b/src/lib/hmac.c
new file mode 100644
--- /dev/null
+++ b/src/lib/hmac.c
@@ -0,0 +1,58 @@
+/*
+ * HMAC (RFC-2104) implementation.
+ *
+ * Copyright (c) 2004 Andrey Panin <pazke at donpac.ru>
+ * Copyright (c) 2011-2012 Florian Zeitz <florob at babelmonkeys.de>
+ *
+ * This software is released under the MIT license.
+ */
+
+#include "lib.h"
+#include "hmac.h"
+#include "safe-memset.h"
+
+void hmac_init(struct hmac_context *ctx, const unsigned char *key,
+ size_t key_len, const struct hash_method *meth)
+{
+ int i;
+ unsigned char k_ipad[64];
+ unsigned char k_opad[64];
+ unsigned char hashedkey[meth->digest_size];
+
+ ctx->hash = meth;
+ ctx->ctx = t_malloc(meth->context_size);
+ ctx->ctxo = t_malloc(meth->context_size);
+
+ if (key_len > 64) {
+ meth->init(ctx->ctx);
+ meth->loop(ctx->ctx, key, key_len);
+ meth->result(ctx->ctx, hashedkey);
+ key = hashedkey;
+ key_len = meth->digest_size;
+ }
+
+ memcpy(k_ipad, key, key_len);
+ memset(k_ipad + key_len, 0, 64 - key_len);
+ memcpy(k_opad, k_ipad, 64);
+
+ for (i = 0; i < 64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ meth->init(ctx->ctx);
+ meth->loop(ctx->ctx, k_ipad, 64);
+ meth->init(ctx->ctxo);
+ meth->loop(ctx->ctxo, k_opad, 64);
+
+ safe_memset(k_ipad, 0, 64);
+ safe_memset(k_opad, 0, 64);
+}
+
+void hmac_final(struct hmac_context *ctx, unsigned char *digest)
+{
+ ctx->hash->result(ctx->ctx, digest);
+
+ ctx->hash->loop(ctx->ctxo, digest, ctx->hash->digest_size);
+ ctx->hash->result(ctx->ctxo, digest);
+}
diff --git a/src/lib/hmac.h b/src/lib/hmac.h
new file mode 100644
--- /dev/null
+++ b/src/lib/hmac.h
@@ -0,0 +1,23 @@
+#ifndef HMAC_H
+#define HMAC_H
+
+#include "hash-method.h"
+#include "sha1.h"
+
+struct hmac_context {
+ void *ctx, *ctxo;
+ const struct hash_method *hash;
+};
+
+void hmac_init(struct hmac_context *ctx, const unsigned char *key,
+ size_t key_len, const struct hash_method *meth);
+void hmac_final(struct hmac_context *ctx, unsigned char *digest);
+
+
+static inline void
+hmac_update(struct hmac_context *ctx, const void *data, size_t size)
+{
+ ctx->hash->loop(ctx->ctx, data, size);
+}
+
+#endif
More information about the dovecot
mailing list