[Dovecot] [PATCH, RFC 1/13] OTP: hash generation

Andrey Panin pazke at donpac.ru
Mon Jun 26 15:57:57 EEST 2006


Add OTP hash generation functions.

diff -urdpNX /usr/share/dontdiff -x Makefile dovecot.vanilla/src/lib-otp/otp-hash.c dovecot/src/lib-otp/otp-hash.c
--- dovecot.vanilla/src/lib-otp/otp-hash.c	1970-01-01 03:00:00.000000000 +0300
+++ dovecot/src/lib-otp/otp-hash.c	2006-06-23 13:44:31.011913912 +0400
@@ -0,0 +1,163 @@
+/*
+ * OTP hash generaion.
+ *
+ * Copyright (c) 2006 Andrey Panin <pazke at donpac.ru>
+ *
+ * This software is released under the MIT license.
+ */
+
+#include "lib.h"
+#include "md4.h"
+#include "md5.h"
+#include "sha1.h"
+
+#include "otp.h"
+
+struct digest {
+	const char *name;
+	void (*init)(void *ctx);
+	void (*update)(void *ctx, const void *data, const size_t size);
+	void (*final)(void *ctx, void *res);
+	void (*otp_final)(void *ctx, void *res);
+};
+
+struct digest_context {
+	struct digest *digest;
+	union {
+		struct md4_context md4_ctx;
+		struct md5_context md5_ctx;
+		struct sha1_ctxt sha1_ctx;
+	} ctx;
+};
+
+static void md4_fold(struct md4_context *ctx, void *res)
+{
+	uint32_t tmp[4], *p = res;
+
+	md4_final(ctx, (unsigned char *) tmp);
+
+	*p++ = tmp[0] ^ tmp[2];
+	*p = tmp[1] ^ tmp[3];
+}
+
+static void md5_fold(struct md5_context *ctx, void *res)
+{
+	uint32_t tmp[4], *p = res;
+
+	md5_final(ctx, (unsigned char *) tmp);
+
+	*p++ = tmp[0] ^ tmp[2];
+	*p = tmp[1] ^ tmp[3];
+}
+
+/*
+ * Sometimes I simply can't look at code generated by gcc.
+ */
+static inline uint32_t swab(uint32_t val)
+{
+#if defined(__GNUC__) && defined(__i386__)
+	asm("xchgb %b0, %h0\n"
+	    "rorl $16, %0\n"
+	    "xchgb %b0, %h0\n"
+	    :"=q" (val)
+	    : "0" (val));
+#else
+	val = ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+		((val & 0xff0000) >> 8) | ((val >> 24) & 0xff);
+#endif
+	return val;
+}
+
+static void sha1_fold(struct sha1_ctxt *ctx, void *res)
+{
+	uint32_t tmp[5], *p = res;
+
+	sha1_result(ctx, tmp);
+
+	*p++ = swab(tmp[0] ^ tmp[2] ^ tmp[4]);
+	*p = swab(tmp[1] ^ tmp[3]);
+}
+
+
+#define F(name) ((void *) (name))
+
+static struct digest digests[] = {
+	{ "md4", F(md4_init), F(md4_update), F(md4_final), F(md4_fold) },
+	{ "md5", F(md5_init), F(md5_update), F(md5_final), F(md5_fold) },
+	{ "sha1", F(sha1_init), F(sha1_loop),  F(sha1_result), F(sha1_fold) },
+};
+
+#define N_DIGESTS (int)(sizeof(digests) / sizeof(digests[0]))
+
+#undef F
+
+const char * digest_name(int algo)
+{
+	return (algo < N_DIGESTS) ? digests[algo].name : NULL;
+}
+
+int digest_find(const char *name)
+{
+	int i;
+
+	for (i = 0; i < N_DIGESTS; i++)
+		if (strcmp(name, digests[i].name) == 0)
+			return i;
+
+	return -1;
+}
+
+int digest_init(struct digest_context *ctx, const int algo)
+{
+	i_assert(algo >= 0);
+
+	ctx->digest = digests + algo;
+
+	ctx->digest->init((void *) &ctx->ctx);
+
+	return 0;
+}
+
+void digest_update(struct digest_context *ctx, const void *data,
+		 const size_t size)
+{
+	ctx->digest->update((void *) &ctx->ctx, data, size);
+}
+
+void digest_final(struct digest_context *ctx, unsigned char *result)
+{
+	ctx->digest->final((void *) &ctx->ctx, result);
+}
+
+void digest_otp_final(struct digest_context *ctx, unsigned char *result)
+{
+	ctx->digest->otp_final((void *) &ctx->ctx, result);
+}
+
+
+void otp_hash(int algo, const char *seed, const char *passphrase,
+	      int step, unsigned char *result)
+{
+	struct digest_context ctx;
+
+	digest_init(&ctx, algo);
+	digest_update(&ctx, seed, strlen(seed));
+	digest_update(&ctx, passphrase, strlen(passphrase));
+	digest_otp_final(&ctx, result);
+
+	while (step--) {
+		digest_init(&ctx, algo);
+		digest_update(&ctx, result, OTP_HASH_SIZE);
+		digest_otp_final(&ctx, result);
+	}
+}
+
+void otp_next_hash(int algo, const unsigned char *prev,
+		   unsigned char *result)
+{
+	struct digest_context ctx;
+
+	digest_init(&ctx, algo);
+	digest_update(&ctx, prev, OTP_HASH_SIZE);
+	digest_otp_final(&ctx, result);
+}
diff -urdpNX /usr/share/dontdiff -x Makefile dovecot.vanilla/src/lib-otp/otp-hash.h dovecot/src/lib-otp/otp-hash.h
--- dovecot.vanilla/src/lib-otp/otp-hash.h	1970-01-01 03:00:00.000000000 +0300
+++ dovecot/src/lib-otp/otp-hash.h	2006-06-23 13:44:31.011913912 +0400
@@ -0,0 +1,25 @@
+#ifndef __OTP_HASH_H__
+#define __OTP_HASH_H__
+
+struct digest_context;
+
+enum {
+	OTP_HASH_MD4,
+	OTP_HASH_MD5,
+	OTP_HASH_SHA1,
+};
+
+int digest_find(const char *name);
+int digest_init(struct digest_context *ctx, const int algo);
+void digest_update(struct digest_context *ctx, const void *data,
+		   const size_t size);
+void digest_final(struct digest_context *ctx, unsigned char *result);
+void digest_otp_final(struct digest_context *ctx, unsigned char *result);
+const char * digest_name(int algo);
+
+void otp_hash(int algo, const char *seed, const char *passphrase,
+	      int step, unsigned char *result);
+
+void otp_next_hash(int algo, const unsigned char *prev, unsigned char *result);
+
+#endif	/* __OTP_HASH_H__ */



More information about the dovecot mailing list