bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

md2, md2-tests, gc-md2, gc-md2 and some gc fixes


From: Simon Josefsson
Subject: md2, md2-tests, gc-md2, gc-md2 and some gc fixes
Date: Fri, 28 Oct 2005 11:35:05 +0200
User-agent: Gnus/5.110004 (No Gnus v0.4) Emacs/22.0.50 (gnu/linux)

I have installed the patch below, we needed MD2 in GnuTLS.

* Libgcrypt doesn't have MD2, so the gc-md2 module unconditionally
  depends on the md2 module.

* I made the md2.? API similar to md5.? etc, but the distinction
  between md2_process_bytes and md2_process_blocks is blurred.  We
  should really separate the non-crypto part of these files...

Thanks!

Index: ChangeLog
===================================================================
RCS file: /cvsroot/gnulib/gnulib/ChangeLog,v
retrieving revision 1.441
diff -u -p -r1.441 ChangeLog
--- ChangeLog   27 Oct 2005 17:46:54 -0000      1.441
+++ ChangeLog   28 Oct 2005 09:32:27 -0000
@@ -1,3 +1,9 @@
+2005-10-28  Simon Josefsson  <address@hidden>
+
+       * tests/test-gc-md2.c, tests/test-md2.c: New files.
+
+       * modules/md2, modules/md2-tests: New files.
+
 2005-10-27  Paul Eggert  <address@hidden>
 
        * modules/verify (License): Change from GPL to LGPL.  This is a
Index: modules/md2
===================================================================
RCS file: modules/md2
diff -N modules/md2
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/md2 28 Oct 2005 09:32:27 -0000
@@ -0,0 +1,25 @@
+Description:
+Compute MD2 checksum.
+
+Files:
+lib/md2.h
+lib/md2.c
+m4/md2.m4
+
+Depends-on:
+stdint
+minmax
+
+configure.ac:
+gl_MD2
+
+Makefile.am:
+
+Include:
+"md2.h"
+
+License:
+LGPL
+
+Maintainer:
+Simon Josefsson
Index: modules/md2-tests
===================================================================
RCS file: modules/md2-tests
diff -N modules/md2-tests
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/md2-tests   28 Oct 2005 09:32:27 -0000
@@ -0,0 +1,11 @@
+Files:
+tests/test-md2.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-md2
+noinst_PROGRAMS += test-md2
+test_md2_SOURCES = test-md2.c
Index: modules/gc-md2
===================================================================
RCS file: modules/gc-md2
diff -N modules/gc-md2
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/gc-md2      28 Oct 2005 09:32:27 -0000
@@ -0,0 +1,25 @@
+Description:
+Generic crypto wrappers for MD2 functions.
+
+Files:
+m4/gc-md2.m4
+
+Depends-on:
+stdint
+gc
+minmax
+md2
+
+configure.ac:
+gl_GC_MD2
+
+Makefile.am:
+
+Include:
+"gc.h"
+
+License:
+LGPL
+
+Maintainer:
+Simon Josefsson
Index: modules/gc-md2-tests
===================================================================
RCS file: modules/gc-md2-tests
diff -N modules/gc-md2-tests
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ modules/gc-md2-tests        28 Oct 2005 09:32:27 -0000
@@ -0,0 +1,11 @@
+Files:
+tests/test-gc-md2.c
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-gc-md2
+noinst_PROGRAMS += test-gc-md2
+test_gc_md2_SOURCES = test-gc-md2.c
Index: m4/ChangeLog
===================================================================
RCS file: /cvsroot/gnulib/gnulib/m4/ChangeLog,v
retrieving revision 1.754
diff -u -p -r1.754 ChangeLog
--- m4/ChangeLog        22 Oct 2005 15:37:28 -0000      1.754
+++ m4/ChangeLog        28 Oct 2005 09:32:28 -0000
@@ -1,3 +1,7 @@
+2005-10-28  Simon Josefsson  <address@hidden>
+
+       * gc-md2.m4, md2.m4: New file.
+
 2005-10-22  Simon Josefsson  <address@hidden>
 
        * gc.m4: Don't be fooled by --disable-*random-device parameters,
Index: m4/md2.m4
===================================================================
RCS file: m4/md2.m4
diff -N m4/md2.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/md2.m4   28 Oct 2005 09:32:28 -0000
@@ -0,0 +1,11 @@
+# md2.m4 serial 1
+dnl Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_MD2],
+[
+  AC_LIBSOURCES([md2.c, md2.h])
+  AC_LIBOBJ([md2])
+])
Index: m4/gc-md2.m4
===================================================================
RCS file: m4/gc-md2.m4
diff -N m4/gc-md2.m4
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ m4/gc-md2.m4        28 Oct 2005 09:32:28 -0000
@@ -0,0 +1,10 @@
+# gc-md2.m4 serial 1
+dnl Copyright (C) 2005 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_GC_MD2],
+[
+  AC_DEFINE(GC_USE_MD2, 1, [Define if you want to support MD2 through GC.])
+])
Index: lib/ChangeLog
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/ChangeLog,v
retrieving revision 1.1037
diff -u -p -r1.1037 ChangeLog
--- lib/ChangeLog       24 Oct 2005 19:14:09 -0000      1.1037
+++ lib/ChangeLog       28 Oct 2005 09:32:29 -0000
@@ -1,3 +1,14 @@
+2005-10-28  Simon Josefsson  <address@hidden>
+
+       * gc.h: Add MD2 and RMD160 length defines.  Add prototypes.
+
+       * gc-libgcrypt.c: Add MD2 (which is not available through
+       libgcrypt).
+
+       * gc-gnulib.c: Add MD2.  Implement gc_hash_* API.
+
+       * md2.h, md2.c: New files.
+
 2005-10-24  Simon Josefsson  <address@hidden>
 
        * md4.h: Shrink buffer size, now that we changed the type.
Index: lib/md2.h
===================================================================
RCS file: lib/md2.h
diff -N lib/md2.h
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/md2.h   28 Oct 2005 09:32:29 -0000
@@ -0,0 +1,82 @@
+/* Declarations of functions and data types used for MD2 sum
+   library functions.
+   Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+#ifndef MD2_H
+# define MD2_H 1
+
+# include <stdio.h>
+# include <stdint.h>
+
+# define MD2_DIGEST_SIZE 16
+
+/* Structure to save state of computation between the single steps.  */
+struct md2_ctx
+{
+  unsigned char chksum[16], X[48], buf[16];
+  size_t curlen;
+};
+
+
+/* Initialize structure containing state of computation. */
+extern void md2_init_ctx (struct md2_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void md2_process_block (const void *buffer, size_t len,
+                              struct md2_ctx *ctx);
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+extern void md2_process_bytes (const void *buffer, size_t len,
+                              struct md2_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF be correctly
+   aligned for a 32 bits value.  */
+extern void *md2_finish_ctx (struct md2_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+extern void *md2_read_ctx (const struct md2_ctx *ctx, void *resbuf);
+
+
+/* Compute MD2 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int md2_stream (FILE *stream, void *resblock);
+
+/* Compute MD2 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+extern void *md2_buffer (const char *buffer, size_t len, void *resblock);
+
+#endif
Index: lib/md2.c
===================================================================
RCS file: lib/md2.c
diff -N lib/md2.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ lib/md2.c   28 Oct 2005 09:32:29 -0000
@@ -0,0 +1,277 @@
+/* Functions to compute MD2 message digest of files or memory blocks.
+   according to the definition of MD2 in RFC 1319 from April 1992.
+   Copyright (C) 1995,1996,1997,1999,2000,2001,2002,2003,2005
+   Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+
+   This program 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 General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Adapted by Simon Josefsson from public domain Libtomcrypt 1.06 by
+   Tom St Denis. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "md2.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include <minmax.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+#define BLOCKSIZE 4096
+#if BLOCKSIZE % 64 != 0
+# error "invalid BLOCKSIZE"
+#endif
+
+static void md2_update_chksum (struct md2_ctx *md);
+static void md2_compress (struct md2_ctx *md);
+
+/* Initialize structure containing state of computation.
+   (RFC 1319, 3.3: Step 3)  */
+void
+md2_init_ctx (struct md2_ctx *ctx)
+{
+  memset (ctx->X, 0, sizeof (ctx->X));
+  memset (ctx->chksum, 0, sizeof (ctx->chksum));
+  memset (ctx->buf, 0, sizeof (ctx->buf));
+  ctx->curlen = 0;
+}
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md2_read_ctx (const struct md2_ctx *ctx, void *resbuf)
+{
+  memcpy (resbuf, ctx->X, 16);
+
+  return resbuf;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md2_finish_ctx (struct md2_ctx *ctx, void *resbuf)
+{
+  unsigned long i, k;
+
+  /* pad the message */
+  k = 16 - ctx->curlen;
+  for (i = ctx->curlen; i < 16; i++)
+    {
+      ctx->buf[i] = (unsigned char) k;
+    }
+
+  /* hash and update */
+  md2_compress (ctx);
+  md2_update_chksum (ctx);
+
+  /* hash checksum */
+  memcpy (ctx->buf, ctx->chksum, 16);
+  md2_compress (ctx);
+
+  return md2_read_ctx (ctx, resbuf);
+}
+
+/* Compute MD2 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md2_stream (FILE *stream, void *resblock)
+{
+  struct md2_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md2_init_ctx (&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1)
+    {
+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+         computation function processes the whole buffer so that with the
+         next round of the loop another block can be read.  */
+      size_t n;
+      sum = 0;
+
+      /* Read block.  Take care for partial reads.  */
+      while (1)
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+
+         if (sum == BLOCKSIZE)
+           break;
+
+         if (n == 0)
+           {
+             /* Check for the error flag IFF N == 0, so that we don't
+                exit the loop after a partial read due to e.g., EAGAIN
+                or EWOULDBLOCK.  */
+             if (ferror (stream))
+               return 1;
+             goto process_partial_block;
+           }
+
+         /* We've read at least one byte, so ignore errors.  But always
+            check for EOF, since feof may be true even though N > 0.
+            Otherwise, we could end up calling fread after EOF.  */
+         if (feof (stream))
+           goto process_partial_block;
+       }
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+         BLOCKSIZE % 64 == 0
+       */
+      md2_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+process_partial_block:;
+
+  /* Process any remaining bytes.  */
+  if (sum > 0)
+    md2_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md2_finish_ctx (&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *
+md2_buffer (const char *buffer, size_t len, void *resblock)
+{
+  struct md2_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md2_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md2_process_block (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md2_finish_ctx (&ctx, resblock);
+}
+
+void
+md2_process_bytes (const void *buffer, size_t len, struct md2_ctx *ctx)
+{
+  const char *in = buffer;
+  unsigned long n;
+
+  while (len > 0)
+    {
+      n = MIN (len, (16 - ctx->curlen));
+      memcpy (ctx->buf + ctx->curlen, in, (size_t) n);
+      ctx->curlen += n;
+      in += n;
+      len -= n;
+
+      /* is 16 bytes full? */
+      if (ctx->curlen == 16)
+       {
+         md2_compress (ctx);
+         md2_update_chksum (ctx);
+         ctx->curlen = 0;
+       }
+    }
+}
+
+static const unsigned char PI_SUBST[256] = {
+  41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
+  19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
+  76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
+  138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
+  245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
+  148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
+  39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
+  181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
+  150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
+  112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
+  96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
+  85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
+  234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
+  129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
+  8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
+  203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
+  166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
+  31, 26, 219, 153, 141, 51, 159, 17, 131, 20
+};
+
+/* adds 16 bytes to the checksum */
+static void
+md2_update_chksum (struct md2_ctx *ctx)
+{
+  int j;
+  unsigned char L;
+
+  L = ctx->chksum[15];
+  for (j = 0; j < 16; j++)
+    {
+      /* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the
+         reference source code [and test vectors] say otherwise. */
+      L = (ctx->chksum[j] ^= PI_SUBST[(int) (ctx->buf[j] ^ L)] & 255);
+    }
+}
+
+static void
+md2_compress (struct md2_ctx *ctx)
+{
+  size_t j, k;
+  unsigned char t;
+
+  /* copy block */
+  for (j = 0; j < 16; j++)
+    {
+      ctx->X[16 + j] = ctx->buf[j];
+      ctx->X[32 + j] = ctx->X[j] ^ ctx->X[16 + j];
+    }
+
+  t = (unsigned char) 0;
+
+  /* do 18 rounds */
+  for (j = 0; j < 18; j++)
+    {
+      for (k = 0; k < 48; k++)
+       {
+         t = (ctx->X[k] ^= PI_SUBST[(int) (t & 255)]);
+       }
+      t = (t + (unsigned char) j) & 255;
+    }
+}
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.  */
+void
+md2_process_block (const void *buffer, size_t len, struct md2_ctx *ctx)
+{
+  md2_process_bytes (buffer, len, ctx);
+}
Index: lib/gc.h
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/gc.h,v
retrieving revision 1.14
diff -u -p -r1.14 gc.h
--- lib/gc.h    19 Oct 2005 14:54:32 -0000      1.14
+++ lib/gc.h    28 Oct 2005 09:32:29 -0000
@@ -57,8 +57,10 @@ typedef enum Gc_hash_mode Gc_hash_mode;
 
 typedef void *gc_hash_handle;
 
+#define GC_MD2_DIGEST_SIZE 16
 #define GC_MD4_DIGEST_SIZE 16
 #define GC_MD5_DIGEST_SIZE 16
+#define GC_RMD160_DIGEST_SIZE 20
 #define GC_SHA1_DIGEST_SIZE 20
 
 /* Cipher types. */
@@ -141,6 +143,8 @@ extern Gc_rc
 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *out);
 
 /* One-call interface. */
+extern Gc_rc gc_md2 (const void *in, size_t inlen, void *resbuf);
+extern Gc_rc gc_md4 (const void *in, size_t inlen, void *resbuf);
 extern Gc_rc gc_md5 (const void *in, size_t inlen, void *resbuf);
 extern Gc_rc gc_sha1 (const void *in, size_t inlen, void *resbuf);
 extern Gc_rc gc_hmac_md5 (const void *key, size_t keylen,
Index: lib/gc-gnulib.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/gc-gnulib.c,v
retrieving revision 1.14
diff -u -p -r1.14 gc-gnulib.c
--- lib/gc-gnulib.c     21 Oct 2005 13:39:43 -0000      1.14
+++ lib/gc-gnulib.c     28 Oct 2005 09:32:29 -0000
@@ -38,6 +38,9 @@
 #include <errno.h>
 
 /* Hashes. */
+#ifdef GC_USE_MD2
+# include "md2.h"
+#endif
 #ifdef GC_USE_MD4
 # include "md4.h"
 #endif
@@ -537,11 +540,233 @@ gc_cipher_close (gc_cipher_handle handle
 
 /* Hashes. */
 
+#define MAX_DIGEST_SIZE 20
+
+typedef struct _gc_hash_ctx {
+  Gc_hash alg;
+  Gc_hash_mode mode;
+  char hash[MAX_DIGEST_SIZE];
+#ifdef GC_USE_MD2
+  struct md2_ctx md2Context;
+#endif
+#ifdef GC_USE_MD4
+  struct md4_ctx md4Context;
+#endif
+#ifdef GC_USE_MD5
+  struct md5_ctx md5Context;
+#endif
+#ifdef GC_USE_SHA1
+  struct sha1_ctx sha1Context;
+#endif
+} _gc_hash_ctx;
+
+Gc_rc
+gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle)
+{
+  _gc_hash_ctx *ctx;
+  Gc_rc rc = GC_OK;
+
+  ctx = calloc (sizeof (*ctx), 1);
+
+  ctx->alg = hash;
+  ctx->mode = mode;
+
+  switch (hash)
+    {
+#ifdef GC_USE_MD2
+    case GC_MD2:
+      md2_init_ctx (&ctx->md2Context);
+      break;
+#endif
+
+#ifdef GC_USE_MD4
+    case GC_MD4:
+      md4_init_ctx (&ctx->md4Context);
+      break;
+#endif
+
+#ifdef GC_USE_MD5
+    case GC_MD5:
+      md5_init_ctx (&ctx->md5Context);
+      break;
+#endif
+
+#ifdef GC_USE_SHA1
+    case GC_SHA1:
+      sha1_init_ctx (&ctx->sha1Context);
+      break;
+#endif
+
+    default:
+      rc = GC_INVALID_HASH;
+      break;
+    }
+
+  switch (mode)
+    {
+    case 0:
+      break;
+
+    default:
+      rc = GC_INVALID_HASH;
+      break;
+    }
+
+  if (rc == GC_OK)
+    *outhandle = ctx;
+  else
+    free (ctx);
+
+  return rc;
+}
+
+Gc_rc
+gc_hash_clone (gc_hash_handle handle, gc_hash_handle * outhandle)
+{
+  _gc_hash_ctx *in = handle;
+  _gc_hash_ctx *out;
+
+  *outhandle = out = calloc (sizeof (*out), 1);
+  if (!out)
+    return GC_MALLOC_ERROR;
+
+  memcpy (out, in, sizeof (*out));
+
+  return GC_OK;
+}
+
+size_t
+gc_hash_digest_length (Gc_hash hash)
+{
+  size_t len;
+
+  switch (hash)
+    {
+    case GC_MD2:
+      len = GC_MD2_DIGEST_SIZE;
+      break;
+
+    case GC_MD4:
+      len = GC_MD4_DIGEST_SIZE;
+      break;
+
+    case GC_MD5:
+      len = GC_MD5_DIGEST_SIZE;
+      break;
+
+    case GC_RMD160:
+      len = GC_RMD160_DIGEST_SIZE;
+      break;
+
+    case GC_SHA1:
+      len = GC_SHA1_DIGEST_SIZE;
+      break;
+
+    default:
+      return 0;
+    }
+
+  return len;
+}
+
+void
+gc_hash_write (gc_hash_handle handle, size_t len, const char *data)
+{
+  _gc_hash_ctx *ctx = handle;
+
+  switch (ctx->alg)
+    {
+#ifdef GC_USE_MD2
+    case GC_MD2:
+      md2_process_bytes (data, len, &ctx->md2Context);
+      break;
+#endif
+
+#ifdef GC_USE_MD4
+    case GC_MD4:
+      md4_process_bytes (data, len, &ctx->md4Context);
+      break;
+#endif
+
+#ifdef GC_USE_MD5
+    case GC_MD5:
+      md5_process_bytes (data, len, &ctx->md5Context);
+      break;
+#endif
+
+#ifdef GC_USE_SHA1
+    case GC_SHA1:
+      sha1_process_bytes (data, len, &ctx->sha1Context);
+      break;
+#endif
+
+    default:
+      break;
+    }
+}
+
+const char *
+gc_hash_read (gc_hash_handle handle)
+{
+  _gc_hash_ctx *ctx = handle;
+  const char *ret = NULL;
+
+  switch (ctx->alg)
+    {
+#ifdef GC_USE_MD2
+    case GC_MD2:
+      md2_finish_ctx (&ctx->md2Context, ctx->hash);
+      ret = ctx->hash;
+      break;
+#endif
+
+#ifdef GC_USE_MD4
+    case GC_MD4:
+      md4_finish_ctx (&ctx->md4Context, ctx->hash);
+      ret = ctx->hash;
+      break;
+#endif
+
+#ifdef GC_USE_MD5
+    case GC_MD5:
+      md5_finish_ctx (&ctx->md5Context, ctx->hash);
+      ret = ctx->hash;
+      break;
+#endif
+
+#ifdef GC_USE_SHA1
+    case GC_SHA1:
+      sha1_finish_ctx (&ctx->sha1Context, ctx->hash);
+      ret = ctx->hash;
+      break;
+#endif
+
+    default:
+      return NULL;
+    }
+
+  return ret;
+}
+
+void
+gc_hash_close (gc_hash_handle handle)
+{
+  _gc_hash_ctx *ctx = handle;
+
+  free (ctx);
+}
+
 Gc_rc
 gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
 {
   switch (hash)
     {
+#ifdef GC_USE_MD2
+    case GC_MD2:
+      md2_buffer (in, inlen, resbuf);
+      break;
+#endif
+
 #ifdef GC_USE_MD4
     case GC_MD4:
       md4_buffer (in, inlen, resbuf);
@@ -566,6 +791,15 @@ gc_hash_buffer (Gc_hash hash, const void
 
   return GC_OK;
 }
+
+#ifdef GC_USE_MD2
+Gc_rc
+gc_md2 (const void *in, size_t inlen, void *resbuf)
+{
+  md2_buffer (in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
 
 #ifdef GC_USE_MD4
 Gc_rc
Index: lib/gc-libgcrypt.c
===================================================================
RCS file: /cvsroot/gnulib/gnulib/lib/gc-libgcrypt.c,v
retrieving revision 1.12
diff -u -p -r1.12 gc-libgcrypt.c
--- lib/gc-libgcrypt.c  21 Oct 2005 11:44:23 -0000      1.12
+++ lib/gc-libgcrypt.c  28 Oct 2005 09:32:29 -0000
@@ -27,8 +27,14 @@
 /* Get prototype. */
 #include "gc.h"
 
+#include <stdlib.h>
+#include <string.h>
+
 /* Get libgcrypt API. */
 #include <gcrypt.h>
+#ifdef GC_USE_MD2
+# include "md2.h"
+#endif
 
 #include <assert.h>
 
@@ -218,14 +224,35 @@ gc_cipher_close (gc_cipher_handle handle
 
 /* Hashes. */
 
+typedef struct _gc_hash_ctx {
+  Gc_hash alg;
+  Gc_hash_mode mode;
+  gcry_md_hd_t gch;
+#ifdef GC_USE_MD2
+  char hash[GC_MD2_DIGEST_SIZE];
+  struct md2_ctx md2Context;
+#endif
+} _gc_hash_ctx;
+
 Gc_rc
 gc_hash_open (Gc_hash hash, Gc_hash_mode mode, gc_hash_handle * outhandle)
 {
+  _gc_hash_ctx *ctx;
   int gcryalg, gcrymode;
   gcry_error_t err;
+  Gc_rc rc = GC_OK;
+
+  ctx = calloc (sizeof (*ctx), 1);
+
+  ctx->alg = hash;
+  ctx->mode = mode;
 
   switch (hash)
     {
+    case GC_MD2:
+      gcryalg = GCRY_MD_NONE;
+      break;
+
     case GC_MD4:
       gcryalg = GCRY_MD_MD4;
       break;
@@ -243,7 +270,7 @@ gc_hash_open (Gc_hash hash, Gc_hash_mode
       break;
 
     default:
-      return GC_INVALID_HASH;
+      rc = GC_INVALID_HASH;
     }
 
   switch (mode)
@@ -257,24 +284,43 @@ gc_hash_open (Gc_hash hash, Gc_hash_mode
       break;
 
     default:
-      return GC_INVALID_HASH;
+      rc = GC_INVALID_HASH;
     }
 
-  err = gcry_md_open ((gcry_md_hd_t *) outhandle, gcryalg, gcrymode);
-  if (gcry_err_code (err))
-    return GC_INVALID_HASH;
+  if (rc == GC_OK && gcryalg != GCRY_MD_NONE)
+    {
+      err = gcry_md_open (&ctx->gch, gcryalg, gcrymode);
+      if (gcry_err_code (err))
+       rc = GC_INVALID_HASH;
+    }
 
-  return GC_OK;
+  if (rc == GC_OK)
+    *outhandle = ctx;
+  else
+    free (ctx);
+
+  return rc;
 }
 
 Gc_rc
 gc_hash_clone (gc_hash_handle handle, gc_hash_handle * outhandle)
 {
+  _gc_hash_ctx *in = handle;
+  _gc_hash_ctx *out;
   int err;
 
-  err = gcry_md_copy ((gcry_md_hd_t *) outhandle, (gcry_md_hd_t) handle);
+  *outhandle = out = calloc (sizeof (*out), 1);
+  if (!out)
+    return GC_MALLOC_ERROR;
+
+  memcpy (out, in, sizeof (*out));
+
+  err = gcry_md_copy (&out->gch, in->gch);
   if (err)
-    return GC_INVALID_HASH;
+    {
+      free (out);
+      return GC_INVALID_HASH;
+    }
 
   return GC_OK;
 }
@@ -282,52 +328,78 @@ gc_hash_clone (gc_hash_handle handle, gc
 size_t
 gc_hash_digest_length (Gc_hash hash)
 {
-  int gcryalg;
+  size_t len;
 
   switch (hash)
     {
+    case GC_MD2:
+      len = GC_MD2_DIGEST_SIZE;
+      break;
+
     case GC_MD4:
-      gcryalg = GCRY_MD_MD4;
+      len = GC_MD4_DIGEST_SIZE;
       break;
 
     case GC_MD5:
-      gcryalg = GCRY_MD_MD5;
+      len = GC_MD5_DIGEST_SIZE;
       break;
 
-    case GC_SHA1:
-      gcryalg = GCRY_MD_SHA1;
+    case GC_RMD160:
+      len = GC_RMD160_DIGEST_SIZE;
       break;
 
-    case GC_RMD160:
-      gcryalg = GCRY_MD_RMD160;
+    case GC_SHA1:
+      len = GC_SHA1_DIGEST_SIZE;
       break;
 
     default:
       return 0;
     }
 
-  return gcry_md_get_algo_dlen (gcryalg);
+  return len;
 }
 
 void
 gc_hash_hmac_setkey (gc_hash_handle handle, size_t len, const char *key)
 {
-  gcry_md_setkey ((gcry_md_hd_t) handle, key, len);
+  _gc_hash_ctx *ctx = handle;
+#ifdef GC_USE_MD2
+  if (ctx->alg != GC_MD2)
+#endif
+    gcry_md_setkey (ctx->gch, key, len);
 }
 
 void
 gc_hash_write (gc_hash_handle handle, size_t len, const char *data)
 {
-  gcry_md_write ((gcry_md_hd_t) handle, data, len);
+  _gc_hash_ctx *ctx = handle;
+
+#ifdef GC_USE_MD2
+  if (ctx->alg == GC_MD2)
+    md2_process_bytes (data, len, &ctx->md2Context);
+  else
+#endif
+    gcry_md_write (ctx->gch, data, len);
 }
 
 const char *
 gc_hash_read (gc_hash_handle handle)
 {
+  _gc_hash_ctx *ctx = handle;
   const char *digest;
 
-  gcry_md_final ((gcry_md_hd_t) handle);
-  digest = gcry_md_read ((gcry_md_hd_t) handle, 0);
+#ifdef GC_USE_MD2
+  if (ctx->alg == GC_MD2)
+    {
+      md2_finish_ctx (&ctx->md2Context, ctx->hash);
+      digest = ctx->hash;
+    }
+  else
+#endif
+    {
+      gcry_md_final (ctx->gch);
+      digest = gcry_md_read (ctx->gch, 0);
+    }
 
   return digest;
 }
@@ -335,7 +407,14 @@ gc_hash_read (gc_hash_handle handle)
 void
 gc_hash_close (gc_hash_handle handle)
 {
-  gcry_md_close ((gcry_md_hd_t) handle);
+  _gc_hash_ctx *ctx = handle;
+
+#ifdef GC_USE_MD2
+  if (ctx->alg != GC_MD2)
+#endif
+    gcry_md_close (ctx->gch);
+
+  free (ctx);
 }
 
 Gc_rc
@@ -345,6 +424,13 @@ gc_hash_buffer (Gc_hash hash, const void
 
   switch (hash)
     {
+#ifdef GC_USE_MD2
+    case GC_MD2:
+      md2_buffer (in, inlen, resbuf);
+      return GC_OK;
+      break;
+#endif
+
 #ifdef GC_USE_MD4
     case GC_MD4:
       gcryalg = GCRY_MD_MD4;
@@ -379,6 +465,15 @@ gc_hash_buffer (Gc_hash hash, const void
 }
 
 /* One-call interface. */
+
+#ifdef GC_USE_MD2
+Gc_rc
+gc_md2 (const void *in, size_t inlen, void *resbuf)
+{
+  md2_buffer (in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
 
 #ifdef GC_USE_MD4
 Gc_rc
Index: tests/test-md2.c
===================================================================
RCS file: tests/test-md2.c
diff -N tests/test-md2.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/test-md2.c    28 Oct 2005 09:32:29 -0000
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.  */
+
+/* Written by Simon Josefsson. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "md2.h"
+
+int
+main (int argc, char *argv[])
+{
+  const char *in1 = "abc";
+  const char *out1 =
+    "\xda\x85\x3b\x0d\x3f\x88\xd9\x9b\x30\x28\x3a\x69\xe6\xde\xd6\xbb";
+  const char *in2 = "abcdefghijklmnopqrstuvwxyz";
+  const char *out2 =
+    "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b";
+  char buf[MD2_DIGEST_SIZE];
+
+  if (memcmp (md2_buffer (in1, strlen (in1), buf), out1, MD2_DIGEST_SIZE) !=
+      0)
+    {
+      size_t i;
+      printf ("expected:\n");
+      for (i = 0; i < MD2_DIGEST_SIZE; i++)
+       printf ("%02x ", out1[i] & 0xFF);
+      printf ("\ncomputed:\n");
+      for (i = 0; i < MD2_DIGEST_SIZE; i++)
+       printf ("%02x ", buf[i] & 0xFF);
+      printf ("\n");
+      return 1;
+    }
+
+  if (memcmp (md2_buffer (in2, strlen (in2), buf), out2, MD2_DIGEST_SIZE) !=
+      0)
+    {
+      size_t i;
+      printf ("expected:\n");
+      for (i = 0; i < MD2_DIGEST_SIZE; i++)
+       printf ("%02x ", out2[i] & 0xFF);
+      printf ("\ncomputed:\n");
+      for (i = 0; i < MD2_DIGEST_SIZE; i++)
+       printf ("%02x ", buf[i] & 0xFF);
+      printf ("\n");
+      return 1;
+    }
+
+  return 0;
+}
Index: tests/test-gc-md2.c
===================================================================
RCS file: tests/test-gc-md2.c
diff -N tests/test-gc-md2.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/test-gc-md2.c 28 Oct 2005 09:32:29 -0000
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2005 Free Software Foundation
+ * Written by Simon Josefsson
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include "gc.h"
+
+int
+main (int argc, char *argv[])
+{
+  Gc_rc rc;
+  gc_hash_handle h;
+
+  rc = gc_init ();
+  if (rc != GC_OK)
+    {
+      printf ("gc_init() failed\n");
+      return 1;
+    }
+
+  /* Test vectors from RFC 1319. */
+
+  {
+    char *in = "abcdefghijklmnopqrstuvwxyz";
+    size_t inlen = strlen (in);
+    char *expect =
+      "\x4e\x8d\xdf\xf3\x65\x02\x92\xab\x5a\x41\x08\xc3\xaa\x47\x94\x0b";
+    char out[16];
+    const char *p;
+
+    if (gc_md2 (in, inlen, out) != 0)
+      {
+       printf ("gc_md2 call failed\n");
+       return 1;
+      }
+
+    if (memcmp (out, expect, 16) != 0)
+      {
+       size_t i;
+       printf ("md2 1 missmatch. expected:\n");
+       for (i = 0; i < 16; i++)
+         printf ("%02x ", expect[i] & 0xFF);
+       printf ("\ncomputed:\n");
+       for (i = 0; i < 16; i++)
+         printf ("%02x ", out[i] & 0xFF);
+       printf ("\n");
+       return 1;
+      }
+
+    if (gc_hash_buffer (GC_MD2, in, inlen, out) != 0)
+      {
+       printf ("gc_hash_buffer(MD2) call failed\n");
+       return 1;
+      }
+
+    if (memcmp (out, expect, 16) != 0)
+      {
+       size_t i;
+       printf ("md2 2 missmatch. expected:\n");
+       for (i = 0; i < 16; i++)
+         printf ("%02x ", expect[i] & 0xFF);
+       printf ("\ncomputed:\n");
+       for (i = 0; i < 16; i++)
+         printf ("%02x ", out[i] & 0xFF);
+       printf ("\n");
+       return 1;
+      }
+
+    if (gc_hash_digest_length (GC_MD2) != 16)
+      {
+       printf ("gc_hash_digest_length (GC_MD2) failed\n");
+       return 1;
+      }
+
+    if ((rc = gc_hash_open (GC_MD2, 0, &h)) != GC_OK)
+      {
+       printf ("gc_hash_open(GC_MD2) failed (%d)\n", rc);
+       return 1;
+      }
+
+    gc_hash_write (h, inlen, in);
+
+    p = gc_hash_read (h);
+
+    if (!p)
+      {
+       printf ("gc_hash_read failed\n");
+       return 1;
+      }
+
+    if (memcmp (p, expect, 16) != 0)
+       {
+       size_t i;
+       printf ("md2 3 missmatch. expected:\n");
+       for (i = 0; i < 16; i++)
+         printf ("%02x ", expect[i] & 0xFF);
+       printf ("\ncomputed:\n");
+       for (i = 0; i < 16; i++)
+         printf ("%02x ", p[i] & 0xFF);
+       printf ("\n");
+       return 1;
+      }
+
+    gc_hash_close (h);
+  }
+
+  gc_done ();
+
+  return 0;
+}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]