Mercurial > dovecot > original-hg > dovecot-1.2
view src/lib-otp/otp-hash.c @ 9565:7c447e8c24fe HEAD
maildir: If we detect MH as the cause of unexpunging, log it in the error message.
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Thu, 29 Apr 2010 20:43:16 +0300 |
parents | 406c9a863f26 |
children |
line wrap: on
line source
/* * OTP hash generaion. * * Copyright (c) 2006 Andrey Panin <pazke@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 { const 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(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_uint32(tmp[0] ^ tmp[2] ^ tmp[4]); *p = swab_uint32(tmp[1] ^ tmp[3]); } #define F(name) ((void (*)()) (name)) static const 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) }, }; #undef F const char *digest_name(unsigned int algo) { i_assert(algo < N_ELEMENTS(digests)); return digests[algo].name; } int digest_find(const char *name) { unsigned int i; for (i = 0; i < N_ELEMENTS(digests); i++) if (strcmp(name, digests[i].name) == 0) return i; return -1; } int digest_init(struct digest_context *ctx, const unsigned int algo) { i_assert(algo < N_ELEMENTS(digests)); ctx->digest = digests + algo; ctx->digest->init(&ctx->ctx); return 0; } void digest_update(struct digest_context *ctx, const void *data, const size_t size) { ctx->digest->update(&ctx->ctx, data, size); } void digest_final(struct digest_context *ctx, unsigned char *result) { ctx->digest->final(&ctx->ctx, result); } void digest_otp_final(struct digest_context *ctx, unsigned char *result) { ctx->digest->otp_final(&ctx->ctx, result); } void otp_hash(unsigned int algo, const char *seed, const char *passphrase, unsigned 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-- > 0) { digest_init(&ctx, algo); digest_update(&ctx, result, OTP_HASH_SIZE); digest_otp_final(&ctx, result); } } void otp_next_hash(unsigned 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); }