summaryrefslogtreecommitdiff
path: root/src/skey/md4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/skey/md4.c')
-rw-r--r--src/skey/md4.c335
1 files changed, 335 insertions, 0 deletions
diff --git a/src/skey/md4.c b/src/skey/md4.c
new file mode 100644
index 0000000..914f101
--- /dev/null
+++ b/src/skey/md4.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2001 Nikos Mavroyanopoulos
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Library General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * The algorithm is due to Ron Rivest. This code is based on code
+ * written by Colin Plumb in 1993.
+ */
+
+
+#include <string.h>
+#include <stdlib.h>
+#include "config.h"
+#include "skey.h"
+#include "skeyutil.h"
+#include "md4.h"
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len) /* Nothing */
+#else
+static void byteReverse(unsigned char *buf, unsigned longs);
+
+
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+ guint32 t;
+ do {
+ t = (guint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+ ((unsigned) buf[1] << 8 | buf[0]);
+ *(guint32 *) buf = t;
+ buf += 4;
+ } while (--longs);
+}
+#endif
+
+#define rotl32(x,n) (((x) << ((guint32)(n))) | ((x) >> (32 - (guint32)(n))))
+
+/*
+ * Start MD4 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void MD4Init(MD4_CTX *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bits[0] = 0;
+ ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void MD4Update(MD4_CTX *ctx, unsigned char const *buf,
+ unsigned len)
+{
+ register guint32 t;
+
+ /* Update bitcount */
+
+ t = ctx->bits[0];
+ if ((ctx->bits[0] = t + ((guint32) len << 3)) < t)
+ ctx->bits[1]++; /* Carry from low to high */
+ ctx->bits[1] += len >> 29;
+
+ t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
+
+ /* Handle any leading odd-sized chunks */
+
+ if (t) {
+ unsigned char *p = (unsigned char *) ctx->in + t;
+
+ t = 64 - t;
+ if (len < t) {
+ memcpy(p, buf, len);
+ return;
+ }
+ memcpy(p, buf, t);
+ byteReverse(ctx->in, 16);
+ MD4Transform(ctx->buf, (guint32 *) ctx->in);
+ buf += t;
+ len -= t;
+ }
+ /* Process data in 64-byte chunks */
+
+ while (len >= 64) {
+ memcpy(ctx->in, buf, 64);
+ byteReverse(ctx->in, 16);
+ MD4Transform(ctx->buf, (guint32 *) ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+
+ memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void MD4Final(unsigned char* digest, MD4_CTX *ctx)
+{
+ unsigned int count;
+ unsigned char *p;
+
+ /* Compute number of bytes mod 64 */
+ count = (ctx->bits[0] >> 3) & 0x3F;
+
+ /* Set the first char of padding to 0x80. This is safe since there is
+ always at least one byte free */
+ p = ctx->in + count;
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 64 bytes */
+ count = 64 - 1 - count;
+
+ /* Pad out to 56 mod 64 */
+ if (count < 8) {
+ /* Two lots of padding: Pad the first block to 64 bytes */
+ memset(p, 0, count);
+ byteReverse(ctx->in, 16);
+ MD4Transform(ctx->buf, (guint32 *) ctx->in);
+
+ /* Now fill the next block with 56 bytes */
+ memset(ctx->in, 0, 56);
+ } else {
+ /* Pad block to 56 bytes */
+ memset(p, 0, count - 8);
+ }
+ byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ((guint32 *) ctx->in)[14] = ctx->bits[0];
+ ((guint32 *) ctx->in)[15] = ctx->bits[1];
+
+ MD4Transform(ctx->buf, (guint32 *) ctx->in);
+ byteReverse((unsigned char *) ctx->buf, 4);
+
+ if (digest!=NULL)
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+/* The three core functions */
+
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+
+#define FF(a, b, c, d, x, s) { \
+ (a) += F ((b), (c), (d)) + (x); \
+ (a) = rotl32 ((a), (s)); \
+ }
+#define GG(a, b, c, d, x, s) { \
+ (a) += G ((b), (c), (d)) + (x) + (guint32)0x5a827999; \
+ (a) = rotl32 ((a), (s)); \
+ }
+#define HH(a, b, c, d, x, s) { \
+ (a) += H ((b), (c), (d)) + (x) + (guint32)0x6ed9eba1; \
+ (a) = rotl32 ((a), (s)); \
+ }
+
+
+/*
+ * The core of the MD4 algorithm
+ */
+void MD4Transform(guint32 buf[4], guint32 const in[16])
+{
+ register guint32 a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ FF(a, b, c, d, in[0], 3); /* 1 */
+ FF(d, a, b, c, in[1], 7); /* 2 */
+ FF(c, d, a, b, in[2], 11); /* 3 */
+ FF(b, c, d, a, in[3], 19); /* 4 */
+ FF(a, b, c, d, in[4], 3); /* 5 */
+ FF(d, a, b, c, in[5], 7); /* 6 */
+ FF(c, d, a, b, in[6], 11); /* 7 */
+ FF(b, c, d, a, in[7], 19); /* 8 */
+ FF(a, b, c, d, in[8], 3); /* 9 */
+ FF(d, a, b, c, in[9], 7); /* 10 */
+ FF(c, d, a, b, in[10], 11); /* 11 */
+ FF(b, c, d, a, in[11], 19); /* 12 */
+ FF(a, b, c, d, in[12], 3); /* 13 */
+ FF(d, a, b, c, in[13], 7); /* 14 */
+ FF(c, d, a, b, in[14], 11); /* 15 */
+ FF(b, c, d, a, in[15], 19); /* 16 */
+
+ GG(a, b, c, d, in[0], 3); /* 17 */
+ GG(d, a, b, c, in[4], 5); /* 18 */
+ GG(c, d, a, b, in[8], 9); /* 19 */
+ GG(b, c, d, a, in[12], 13); /* 20 */
+ GG(a, b, c, d, in[1], 3); /* 21 */
+ GG(d, a, b, c, in[5], 5); /* 22 */
+ GG(c, d, a, b, in[9], 9); /* 23 */
+ GG(b, c, d, a, in[13], 13); /* 24 */
+ GG(a, b, c, d, in[2], 3); /* 25 */
+ GG(d, a, b, c, in[6], 5); /* 26 */
+ GG(c, d, a, b, in[10], 9); /* 27 */
+ GG(b, c, d, a, in[14], 13); /* 28 */
+ GG(a, b, c, d, in[3], 3); /* 29 */
+ GG(d, a, b, c, in[7], 5); /* 30 */
+ GG(c, d, a, b, in[11], 9); /* 31 */
+ GG(b, c, d, a, in[15], 13); /* 32 */
+
+ HH(a, b, c, d, in[0], 3); /* 33 */
+ HH(d, a, b, c, in[8], 9); /* 34 */
+ HH(c, d, a, b, in[4], 11); /* 35 */
+ HH(b, c, d, a, in[12], 15); /* 36 */
+ HH(a, b, c, d, in[2], 3); /* 37 */
+ HH(d, a, b, c, in[10], 9); /* 38 */
+ HH(c, d, a, b, in[6], 11); /* 39 */
+ HH(b, c, d, a, in[14], 15); /* 40 */
+ HH(a, b, c, d, in[1], 3); /* 41 */
+ HH(d, a, b, c, in[9], 9); /* 42 */
+ HH(c, d, a, b, in[5], 11); /* 43 */
+ HH(b, c, d, a, in[13], 15); /* 44 */
+ HH(a, b, c, d, in[3], 3); /* 45 */
+ HH(d, a, b, c, in[11], 9); /* 46 */
+ HH(c, d, a, b, in[7], 11); /* 47 */
+ HH(b, c, d, a, in[15], 15); /* 48 */
+
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+int MD4Keycrunch( char *result, const char *seed, const char *passphrase)
+{
+ int len;
+ char *buf;
+ MD4_CTX md;
+ guint32 results[4];
+
+ len = strlen(seed) + strlen(passphrase);
+ buf = (char *)malloc(len+1);
+ if (buf == NULL)
+ return -1;
+
+ strcpy(buf, seed);
+ skey_lowcase(buf);
+ strcat(buf, passphrase);
+ skey_sevenbit(buf);
+
+ MD4Init(&md);
+ MD4Update(&md, (unsigned char *)buf, len);
+ MD4Final((unsigned char *)results, &md);
+ free(buf);
+
+ results[0] ^= results[2];
+ results[1] ^= results[3];
+ memcpy((void *)result, (void *)results, SKEY_SIZE);
+
+ return 0;
+}
+
+
+void MD4SKey(char *x)
+{
+ MD4_CTX md;
+ guint32 results[4];
+
+ MD4Init(&md);
+ MD4Update(&md, (unsigned char *)x, SKEY_SIZE);
+ MD4Final((unsigned char *)results, &md);
+
+ results[0] ^= results[2];
+ results[1] ^= results[3];
+
+ memcpy((void *)x, (void *)results, SKEY_SIZE);
+}
+
+#ifdef MD4_MAIN
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ MD4_CTX *md4;
+ unsigned char digest[16];
+ unsigned char data[1024];
+ int i, r;
+
+ memset(digest, 0, 16);
+ printf("MD4 digest algorithm. End with Ctrl-D:\n");
+
+ md4 = (MD4_CTX *)malloc(sizeof(MD4_CTX));
+ MD4Init(md4);
+ do {
+ r = read(0, data, sizeof data);
+ MD4Update(md4, data, r);
+ } while (r);
+
+ MD4Final(digest, md4);
+ printf("MD4 Digest is: ");
+ for (i = 0; i < 16; i++)
+ printf("%02X", digest[i]);
+
+ printf("\n");
+ free(md4);
+ return 0;
+}
+
+#endif