cscvs to tla changeset 139
authorJonathan McDowell <noodles@earth.li>
Mon, 31 May 2004 23:48:30 +0000 (23:48 +0000)
committerJonathan McDowell <noodles@earth.li>
Mon, 31 May 2004 23:48:30 +0000 (23:48 +0000)
Author: noodles
Date: 2004/05/31 22:04:50
Update MD5/SHA1 implementations from sigcheck; these are more portable.

Makefile
bithelp.h [deleted file]
keyid.c
md5.c
md5.h
sha.c [deleted file]
sha.h [deleted file]
sha1.c [new file with mode: 0644]
sha1.h [new file with mode: 0644]

index 199155243aeda23ba8ce1729c07c659479433b50..d626ffdb5547cccb8289e123951fce973b126556 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 #
 # Makefile for onak.
 #
-# $Id: Makefile,v 1.22 2004/05/31 14:16:49 noodles Exp $
+# $Id: Makefile,v 1.23 2004/05/31 22:04:50 noodles Exp $
 #
 
 CC = gcc
@@ -17,11 +17,11 @@ LIBS = -L/usr/local/lib -ldb3
 
 PROGS = add lookup gpgwww onak splitkeys
 CORE_OBJS = armor.o charfuncs.o decodekey.o getcgi.o hash.o keydb_$(DBTYPE).o \
-       keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sha.o md5.o \
+       keyid.o keyindex.o ll.o mem.o onak-conf.o parsekey.o sha1.o md5.o \
        log.o photoid.o wordlist.o
 OBJS = merge.o stats.o sendsync.o cleankey.o $(CORE_OBJS)
-SRCS = armor.c parsekey.c merge.c keyid.c md5.c sha.c main.c getcgi.c stats.c \
-       keyindex.c mem.c lookup.c add.c keydb_$(DBTYPE).c ll.c hash.c \
+SRCS = armor.c parsekey.c merge.c keyid.c md5.c sha1.c main.c getcgi.c mem.c \
+       keyindex.c stats.c lookup.c add.c keydb_$(DBTYPE).c ll.c hash.c \
        gpgwww.c onak-conf.c charfuncs.c sendsync.c log.c photoid.c \
        wordlist.c cleankey.c
 
diff --git a/bithelp.h b/bithelp.h
deleted file mode 100644 (file)
index 76324b4..0000000
--- a/bithelp.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* bithelp.h  -  Some bit manipulation helpers
- *     Copyright (C) 1999 Free Software Foundation, Inc.
- *
- * This file is part of GnuPG.
- *
- * GnuPG 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 of the License, or
- * (at your option) any later version.
- *
- * GnuPG 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * $Id: bithelp.h,v 1.4 2003/10/04 10:21:40 noodles Exp $
- */
-
-#ifndef __BITHELP_H__
-#define __BITHELP_H__
-
-/**
- *     rol - Rotate a 32 bit integer by n bytes
- *     @x: The integer to rotate.
- *     @n: The number of bytes to rotate it by.
- */
-static inline unsigned int rol(unsigned int x, int n)
-{
-       __asm__("roll %%cl,%0"
-               :"=r" (x)
-               :"0" (x),"c" (n));
-       return x;
-}
-
-#endif /* __BITHELP_H__ */
diff --git a/keyid.c b/keyid.c
index 34ab145df0bb0c847ed015896686ce237251cb9b..5149fd640d7e552294aa17c19e17d72cc4db05cf 100644 (file)
--- a/keyid.c
+++ b/keyid.c
@@ -5,16 +5,17 @@
  *
  * Copyright 2002 Project Purple
  *
- * $Id: keyid.c,v 1.9 2004/05/29 02:52:56 noodles Exp $
+ * $Id: keyid.c,v 1.10 2004/05/31 22:04:51 noodles Exp $
  */
 
 #include <sys/types.h>
 
+#include "assert.h"
 #include "keyid.h"
 #include "keystructs.h"
 #include "log.h"
 #include "md5.h"
-#include "sha.h"
+#include "sha1.h"
 
 
 /**
@@ -40,10 +41,9 @@ unsigned char *get_fingerprint(struct openpgp_packet *packet,
        unsigned char *fingerprint,
        size_t *len)
 {
-       SHA1_CONTEXT sha_ctx;
-       MD5_CONTEXT md5_ctx;
+       SHA1_CTX sha_ctx;
+       struct md5_ctx md5_context;
        unsigned char c;
-       unsigned char *buff = NULL;
        size_t         modlen, explen;
 
        assert(fingerprint != NULL);
@@ -54,46 +54,42 @@ unsigned char *get_fingerprint(struct openpgp_packet *packet,
        switch (packet->data[0]) {
        case 2:
        case 3:
-               md5_init(&md5_ctx);
+               md5_init_ctx(&md5_context);
 
                /*
                 * MD5 the modulus and exponent.
                 */
                modlen = ((packet->data[8] << 8) +
                         packet->data[9] + 7) >> 3;
-               md5_write(&md5_ctx, &packet->data[10], modlen);
+               md5_process_bytes(&packet->data[10], modlen, &md5_context);
 
                explen = ((packet->data[10+modlen] << 8) +
                         packet->data[11+modlen] + 7) >> 3;
-               md5_write(&md5_ctx, &packet->data[12 + modlen], explen);
-
-               md5_final(&md5_ctx);
-               buff = md5_read(&md5_ctx);
+               md5_process_bytes(&packet->data[12 + modlen], explen,
+                               &md5_context);
 
+               md5_finish_ctx(&md5_context, fingerprint);
                *len = 16;
-               memcpy(fingerprint, buff, *len);
 
                break;
 
        case 4:
-               sha1_init(&sha_ctx);
+               SHA1Init(&sha_ctx);
                /*
                 * TODO: Can this be 0x99? Are all public key packets old
                 * format with 2 bytes of length data?
                 */
                c = 0x99;
-               sha1_write(&sha_ctx, &c, sizeof(c));
+               SHA1Update(&sha_ctx, &c, sizeof(c));
                c = packet->length >> 8;
-               sha1_write(&sha_ctx, &c, sizeof(c));
+               SHA1Update(&sha_ctx, &c, sizeof(c));
                c = packet->length & 0xFF;
-               sha1_write(&sha_ctx, &c, sizeof(c));
-               sha1_write(&sha_ctx, packet->data,
+               SHA1Update(&sha_ctx, &c, sizeof(c));
+               SHA1Update(&sha_ctx, packet->data,
                        packet->length);
-               sha1_final(&sha_ctx);
-               buff = sha1_read(&sha_ctx);
-
+               SHA1Final(fingerprint, &sha_ctx);
                *len = 20;
-               memcpy(fingerprint, buff, *len);
+
                break;
        default:
                logthing(LOGTHING_ERROR, "Unknown key type: %d",
diff --git a/md5.c b/md5.c
index 5a0785d1851aee39faba4f7f2cc728d497282eef..4930ae20eeebc8c93882a15b121fd494d88099eb 100644 (file)
--- a/md5.c
+++ b/md5.c
-/* md5.c - MD5 Message-Digest Algorithm
- *     Copyright (C) 1995, 1996, 1998, 1999 Free Software Foundation, Inc.
- *
- * according to the definition of MD5 in RFC 1321 from April 1992.
- * NOTE: This is *not* the same file as the one from glibc.
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- *
- * $Id: md5.c,v 1.4 2004/05/27 22:02:05 noodles Exp $
- */
+/* Functions to compute MD5 message digest of files or memory blocks.
+   according to the definition of MD5 in RFC 1321 from April 1992.
+   Copyright (C) 1995,1996,1997,1999,2000,2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
 /* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
-/* heavily modified for GnuPG by <werner.koch@guug.de> */
-/* Heavily modified for CryptNET KeyServer by V. Alex Brennen <vab@cryptnet.net> */
-
-/* Test values:
- * ""                  D4 1D 8C D9 8F 00 B2 04  E9 80 09 98 EC F8 42 7E
- * "a"                 0C C1 75 B9 C0 F1 B6 A8  31 C3 99 E2 69 77 26 61
- * "abc                90 01 50 98 3C D2 4F B0  D6 96 3F 7D 28 E1 7F 72
- * "message digest"    F9 6B 69 7D 7C B7 93 8D  52 5A 2F 31 AA F1 61 D0
- */
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+#include <string.h>
+
 #include "md5.h"
 
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n)                                                       \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#else
+# define SWAP(n) (n)
+#endif
+
+
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
 
-void md5_init( MD5_CONTEXT *ctx )
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void
+md5_init_ctx (ctx)
+     struct md5_ctx *ctx;
 {
-    ctx->A = 0x67452301;
-    ctx->B = 0xefcdab89U;
-    ctx->C = 0x98badcfeU;
-    ctx->D = 0x10325476;
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
 
-    ctx->nblocks = 0;
-    ctx->count = 0;
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
 }
 
-/* These are the four functions used in the four steps of the MD5 algorithm
-   and defined in the RFC 1321.  The first function is a little bit optimized
-   (as found in Colin Plumbs public domain implementation).  */
-/* #define FF(b, c, d) ((b & c) | (~b & d)) */
-#define FF(b, c, d) (d ^ (b & (c ^ d)))
-#define FG(b, c, d) FF (d, b, c)
-#define FH(b, c, d) (b ^ c ^ d)
-#define FI(b, c, d) (c ^ (b | ~d))
-#define DIM(v) (sizeof(v)/sizeof((v)[0]))
+/* Put result from CTX in first 16 bytes following RESBUF.  The result
+   must be in little endian byte order.
 
-/****************
- * transform n*64 bytes
- */
-static void transform( MD5_CONTEXT *ctx, unsigned char *data )
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+void *
+md5_read_ctx (ctx, resbuf)
+     const struct md5_ctx *ctx;
+     void *resbuf;
 {
-    unsigned int correct_words[16];
-    unsigned int A = ctx->A;
-    unsigned int B = ctx->B;
-    unsigned int C = ctx->C;
-    unsigned int D = ctx->D;
-    unsigned int *cwp = correct_words;
-
-    memcpy( correct_words, data, 64 );
-
-
-#define OP(a, b, c, d, s, T)                                       \
-  do                                                               \
-    {                                                              \
-      a += FF (b, c, d) + (*cwp++) + T;            \
-      a = rol(a, s);                                               \
-      a += b;                                                      \
-    }                                                              \
-  while (0)
-
-    /* Before we start, one word about the strange constants.
-       They are defined in RFC 1321 as
-
-       T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
-     */
-
-    /* Round 1.  */
-    OP (A, B, C, D,  7, 0xd76aa478);
-    OP (D, A, B, C, 12, 0xe8c7b756);
-    OP (C, D, A, B, 17, 0x242070db);
-    OP (B, C, D, A, 22, 0xc1bdceee);
-    OP (A, B, C, D,  7, 0xf57c0faf);
-    OP (D, A, B, C, 12, 0x4787c62a);
-    OP (C, D, A, B, 17, 0xa8304613);
-    OP (B, C, D, A, 22, 0xfd469501);
-    OP (A, B, C, D,  7, 0x698098d8);
-    OP (D, A, B, C, 12, 0x8b44f7af);
-    OP (C, D, A, B, 17, 0xffff5bb1);
-    OP (B, C, D, A, 22, 0x895cd7be);
-    OP (A, B, C, D,  7, 0x6b901122);
-    OP (D, A, B, C, 12, 0xfd987193);
-    OP (C, D, A, B, 17, 0xa679438e);
-    OP (B, C, D, A, 22, 0x49b40821);
+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
 
-#undef OP
-#define OP(f, a, b, c, d, k, s, T)  \
-    do                                                               \
-      {                                                              \
-       a += f (b, c, d) + correct_words[k] + T;                      \
-       a = rol(a, s);                                                \
-       a += b;                                                       \
-      }                                                              \
-    while (0)
-
-    /* Round 2.  */
-    OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
-    OP (FG, D, A, B, C,  6,  9, 0xc040b340);
-    OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
-    OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
-    OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
-    OP (FG, D, A, B, C, 10,  9, 0x02441453);
-    OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
-    OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
-    OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
-    OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
-    OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
-    OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
-    OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
-    OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
-    OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
-    OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
-
-    /* Round 3.  */
-    OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
-    OP (FH, D, A, B, C,  8, 11, 0x8771f681);
-    OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
-    OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
-    OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
-    OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
-    OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
-    OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
-    OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
-    OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
-    OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
-    OP (FH, B, C, D, A,  6, 23, 0x04881d05);
-    OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
-    OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
-    OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
-    OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
-
-    /* Round 4.  */
-    OP (FI, A, B, C, D,  0,  6, 0xf4292244);
-    OP (FI, D, A, B, C,  7, 10, 0x432aff97);
-    OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
-    OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
-    OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
-    OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
-    OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
-    OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
-    OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
-    OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
-    OP (FI, C, D, A, B,  6, 15, 0xa3014314);
-    OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
-    OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
-    OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
-    OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
-    OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
-
-    /* Put checksum in context given as argument.  */
-    ctx->A += A;
-    ctx->B += B;
-    ctx->C += C;
-    ctx->D += D;
+  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 *
+md5_finish_ctx (ctx, resbuf)
+     struct md5_ctx *ctx;
+     void *resbuf;
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
 
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3);
+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) |
+                                                       (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  md5_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return md5_read_ctx (ctx, resbuf);
+}
 
-/* The routine updates the message-digest context to
- * account for the presence of each of the characters inBuf[0..inLen-1]
- * in the message whose digest is being computed.
- */
-void md5_write( MD5_CONTEXT *hd, unsigned char *inbuf, size_t inlen)
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+md5_stream (stream, resblock)
+     FILE *stream;
+     void *resblock;
 {
-    if( hd->count == 64 ) { /* flush the buffer */
-       transform( hd, hd->buf );
-       hd->count = 0;
-       hd->nblocks++;
-    }
-    if( !inbuf )
-       return;
-    if( hd->count ) {
-       for( ; inlen && hd->count < 64; inlen-- )
-           hd->buf[hd->count++] = *inbuf++;
-       md5_write( hd, NULL, 0 );
-       if( !inlen )
-           return;
+  /* Important: BLOCKSIZE must be a multiple of 64.  */
+#define BLOCKSIZE 4096
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_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.  */
+      do
+       {
+         n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+         sum += n;
+       }
+      while (sum < BLOCKSIZE && n != 0);
+      if (n == 0 && ferror (stream))
+        return 1;
+
+      /* If end of file is reached, end the loop.  */
+      if (n == 0)
+       break;
+
+      /* Process buffer with BLOCKSIZE bytes.  Note that
+                       BLOCKSIZE % 64 == 0
+       */
+      md5_process_block (buffer, BLOCKSIZE, &ctx);
     }
 
-    while( inlen >= 64 ) {
-       transform( hd, inbuf );
-       hd->count = 0;
-       hd->nblocks++;
-       inlen -= 64;
-       inbuf += 64;
-    }
-    for( ; inlen && hd->count < 64; inlen-- )
-       hd->buf[hd->count++] = *inbuf++;
+  /* Add the last bytes if necessary.  */
+  if (sum > 0)
+    md5_process_bytes (buffer, sum, &ctx);
 
+  /* Construct result in desired memory.  */
+  md5_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 *
+md5_buffer (buffer, len, resblock)
+     const char *buffer;
+     size_t len;
+     void *resblock;
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes (buffer, len, &ctx);
 
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx (&ctx, resblock);
+}
 
-/* The routine final terminates the message-digest computation and
- * ends with the desired message digest in mdContext->digest[0...15].
- * The handle is prepared for a new MD5 cycle.
- * Returns 16 bytes representing the digest.
- */
 
-void md5_final( MD5_CONTEXT *hd )
+void
+md5_process_bytes (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
 {
-    unsigned int t, msb, lsb;
-    unsigned char *p;
-
-    md5_write(hd, NULL, 0); /* flush */;
-
-    msb = 0;
-    t = hd->nblocks;
-    if( (lsb = t << 6) < t ) /* multiply by 64 to make a byte count */
-       msb++;
-    msb += t >> 26;
-    t = lsb;
-    if( (lsb = t + hd->count) < t ) /* add the count */
-       msb++;
-    t = lsb;
-    if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
-       msb++;
-    msb += t >> 29;
-
-    if( hd->count < 56 ) { /* enough room */
-       hd->buf[hd->count++] = 0x80; /* pad */
-       while( hd->count < 56 )
-           hd->buf[hd->count++] = 0;  /* pad */
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0)
+    {
+      size_t left_over = ctx->buflen;
+      size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+      memcpy (&ctx->buffer[left_over], buffer, add);
+      ctx->buflen += add;
+
+      if (ctx->buflen > 64)
+       {
+         md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
+
+         ctx->buflen &= 63;
+         /* The regions in the following copy operation cannot overlap.  */
+         memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+                 ctx->buflen);
+       }
+
+      buffer = (const char *) buffer + add;
+      len -= add;
     }
-    else { /* need one extra block */
-       hd->buf[hd->count++] = 0x80; /* pad character */
-       while( hd->count < 64 )
-           hd->buf[hd->count++] = 0;
-       md5_write(hd, NULL, 0);  /* flush */;
-       memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+/* To check alignment gcc has an appropriate operator.  Other
+   compilers don't.  */
+# if __GNUC__ >= 2
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0)
+# else
+#  define UNALIGNED_P(p) (((md5_uintptr) p) % sizeof (md5_uint32) != 0)
+# endif
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         md5_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
     }
-    /* append the 64 bit count */
-    hd->buf[56] = lsb     ;
-    hd->buf[57] = lsb >>  8;
-    hd->buf[58] = lsb >> 16;
-    hd->buf[59] = lsb >> 24;
-    hd->buf[60] = msb     ;
-    hd->buf[61] = msb >>  8;
-    hd->buf[62] = msb >> 16;
-    hd->buf[63] = msb >> 24;
-    transform( hd, hd->buf );
-
-    p = hd->buf;
-    /* little endian */
-    /*#define X(a) do { *(u32*)p = hd->##a ; p += 4; } while(0)*/
-    /* Unixware's cpp doesn't like the above construct so we do it his way:
-     * (reported by Allan Clark) */
-#define X(a) do { *(unsigned int *)p = (*hd).a ; p += 4; } while(0)
-    X(A);
-    X(B);
-    X(C);
-    X(D);
-#undef X
 
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0)
+    {
+      size_t left_over = ctx->buflen;
+
+      memcpy (&ctx->buffer[left_over], buffer, len);
+      left_over += len;
+      if (left_over >= 64)
+       {
+         md5_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
 }
 
-unsigned char *md5_read(MD5_CONTEXT *hd)
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+
+void
+md5_process_block (buffer, len, ctx)
+     const void *buffer;
+     size_t len;
+     struct md5_ctx *ctx;
 {
-    return hd->buf;
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof (md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp)
+    {
+      md5_uint32 *cwp = correct_words;
+      md5_uint32 A_save = A;
+      md5_uint32 B_save = B;
+      md5_uint32 C_save = C;
+      md5_uint32 D_save = D;
+
+      /* First round: using the given function, the context and a constant
+        the next context is computed.  Because the algorithms processing
+        unit is a 32-bit word and it is determined to work on words in
+        little endian byte order we perhaps have to change the byte order
+        before the computation.  To reduce the work for the next steps
+        we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)                                           \
+      do                                                               \
+        {                                                              \
+         a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;             \
+         ++words;                                                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+        }                                                              \
+      while (0)
+
+      /* It is unfortunate that C does not provide an operator for
+        cyclic rotation.  Hope the C compiler is smart enough.  */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+      /* Before we start, one word to the strange constants.
+        They are defined in RFC 1321 as
+
+        T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+       */
+
+      /* Round 1.  */
+      OP (A, B, C, D,  7, 0xd76aa478);
+      OP (D, A, B, C, 12, 0xe8c7b756);
+      OP (C, D, A, B, 17, 0x242070db);
+      OP (B, C, D, A, 22, 0xc1bdceee);
+      OP (A, B, C, D,  7, 0xf57c0faf);
+      OP (D, A, B, C, 12, 0x4787c62a);
+      OP (C, D, A, B, 17, 0xa8304613);
+      OP (B, C, D, A, 22, 0xfd469501);
+      OP (A, B, C, D,  7, 0x698098d8);
+      OP (D, A, B, C, 12, 0x8b44f7af);
+      OP (C, D, A, B, 17, 0xffff5bb1);
+      OP (B, C, D, A, 22, 0x895cd7be);
+      OP (A, B, C, D,  7, 0x6b901122);
+      OP (D, A, B, C, 12, 0xfd987193);
+      OP (C, D, A, B, 17, 0xa679438e);
+      OP (B, C, D, A, 22, 0x49b40821);
+
+      /* For the second to fourth round we have the possibly swapped words
+        in CORRECT_WORDS.  Redefine the macro to take an additional first
+        argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)                                     \
+      do                                                               \
+       {                                                               \
+         a += f (b, c, d) + correct_words[k] + T;                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+       }                                                               \
+      while (0)
+
+      /* Round 2.  */
+      OP (FG, A, B, C, D,  1,  5, 0xf61e2562);
+      OP (FG, D, A, B, C,  6,  9, 0xc040b340);
+      OP (FG, C, D, A, B, 11, 14, 0x265e5a51);
+      OP (FG, B, C, D, A,  0, 20, 0xe9b6c7aa);
+      OP (FG, A, B, C, D,  5,  5, 0xd62f105d);
+      OP (FG, D, A, B, C, 10,  9, 0x02441453);
+      OP (FG, C, D, A, B, 15, 14, 0xd8a1e681);
+      OP (FG, B, C, D, A,  4, 20, 0xe7d3fbc8);
+      OP (FG, A, B, C, D,  9,  5, 0x21e1cde6);
+      OP (FG, D, A, B, C, 14,  9, 0xc33707d6);
+      OP (FG, C, D, A, B,  3, 14, 0xf4d50d87);
+      OP (FG, B, C, D, A,  8, 20, 0x455a14ed);
+      OP (FG, A, B, C, D, 13,  5, 0xa9e3e905);
+      OP (FG, D, A, B, C,  2,  9, 0xfcefa3f8);
+      OP (FG, C, D, A, B,  7, 14, 0x676f02d9);
+      OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+
+      /* Round 3.  */
+      OP (FH, A, B, C, D,  5,  4, 0xfffa3942);
+      OP (FH, D, A, B, C,  8, 11, 0x8771f681);
+      OP (FH, C, D, A, B, 11, 16, 0x6d9d6122);
+      OP (FH, B, C, D, A, 14, 23, 0xfde5380c);
+      OP (FH, A, B, C, D,  1,  4, 0xa4beea44);
+      OP (FH, D, A, B, C,  4, 11, 0x4bdecfa9);
+      OP (FH, C, D, A, B,  7, 16, 0xf6bb4b60);
+      OP (FH, B, C, D, A, 10, 23, 0xbebfbc70);
+      OP (FH, A, B, C, D, 13,  4, 0x289b7ec6);
+      OP (FH, D, A, B, C,  0, 11, 0xeaa127fa);
+      OP (FH, C, D, A, B,  3, 16, 0xd4ef3085);
+      OP (FH, B, C, D, A,  6, 23, 0x04881d05);
+      OP (FH, A, B, C, D,  9,  4, 0xd9d4d039);
+      OP (FH, D, A, B, C, 12, 11, 0xe6db99e5);
+      OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+      OP (FH, B, C, D, A,  2, 23, 0xc4ac5665);
+
+      /* Round 4.  */
+      OP (FI, A, B, C, D,  0,  6, 0xf4292244);
+      OP (FI, D, A, B, C,  7, 10, 0x432aff97);
+      OP (FI, C, D, A, B, 14, 15, 0xab9423a7);
+      OP (FI, B, C, D, A,  5, 21, 0xfc93a039);
+      OP (FI, A, B, C, D, 12,  6, 0x655b59c3);
+      OP (FI, D, A, B, C,  3, 10, 0x8f0ccc92);
+      OP (FI, C, D, A, B, 10, 15, 0xffeff47d);
+      OP (FI, B, C, D, A,  1, 21, 0x85845dd1);
+      OP (FI, A, B, C, D,  8,  6, 0x6fa87e4f);
+      OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+      OP (FI, C, D, A, B,  6, 15, 0xa3014314);
+      OP (FI, B, C, D, A, 13, 21, 0x4e0811a1);
+      OP (FI, A, B, C, D,  4,  6, 0xf7537e82);
+      OP (FI, D, A, B, C, 11, 10, 0xbd3af235);
+      OP (FI, C, D, A, B,  2, 15, 0x2ad7d2bb);
+      OP (FI, B, C, D, A,  9, 21, 0xeb86d391);
+
+      /* Add the starting values of the context.  */
+      A += A_save;
+      B += B_save;
+      C += C_save;
+      D += D_save;
+    }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
 }
diff --git a/md5.h b/md5.h
index 65a2159a3f703c338775464c9927dc7a08d447a7..57eba211485f4ad1c002775138099a72b266d030 100644 (file)
--- a/md5.h
+++ b/md5.h
@@ -1,23 +1,96 @@
-#ifndef __MD5_H__
-#define __MD5_H__
+/* Declaration of functions and data types used for MD5 sum computing
+   library functions.
+   Copyright (C) 1995,1996,1997,1999,2000,2001 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307 USA.  */
+
+#ifndef _MD5_H
+#define _MD5_H 1
 
 #include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
+#include <sys/types.h>
+typedef u_int32_t md5_uint32;
+typedef size_t md5_uintptr;
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  char buffer[128];
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+extern void md5_init_ctx (struct md5_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 necessary that LEN is a multiple of 64!!! */
+extern void md5_process_block (const void *buffer, size_t len,
+                                     struct md5_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 md5_process_bytes (const void *buffer, size_t len,
+                                     struct md5_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 is correctly
+   aligned for a 32 bits value.  */
+extern void *md5_finish_ctx (struct md5_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 *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf);
 
-#include "bithelp.h"
 
-typedef struct {
-    unsigned int  A,B,C,D;       /* chaining variables */
-    unsigned int  nblocks;
-    unsigned char buf[64];
-    int  count;
-} MD5_CONTEXT;
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int md5_stream (FILE *stream, void *resblock);
 
-void md5_init(MD5_CONTEXT *);
-void md5_write(MD5_CONTEXT *, unsigned char *, size_t);
-void md5_final(MD5_CONTEXT *);
-unsigned char *md5_read(MD5_CONTEXT *);
+/* 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.  */
+extern void *md5_buffer (const char *buffer, size_t len,
+                               void *resblock);
 
-#endif /* __MD5_H__ */
+#endif /* md5.h */
diff --git a/sha.c b/sha.c
deleted file mode 100644 (file)
index 1625cda..0000000
--- a/sha.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/* sha1.c - SHA1 hash function
- *     Copyright (C) 2001 V. Alex Brennen
- *
- * Please see below for more legal information!
- *
- * This file is part of the CryptNET openPGP Public Keyserver (CKS).
- *
- * CKS 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 of the License, or
- * (at your option) any later version.
- *
- * CKS 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
- *
- * $Id: sha.c,v 1.3 2004/05/27 22:02:06 noodles Exp $
- */
-
-/* This file was copied from GnuPG                               */
-/* Some portions Copyright (C) 1998 The Free Software Foundation */
-
-#include "sha.h"
-
-
-/*  Test vectors:
- *
- *  "abc"
- *  A999 3E36 4706 816A BA3E  2571 7850 C26C 9CD0 D89D
- *
- *  "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
- *  8498 3E44 1C3B D26E BAAE  4AA1 F951 29E5 E546 70F1
- */
-
-void sha1_init( SHA1_CONTEXT *hd )
-{
-    hd->h0 = 0x67452301;
-    hd->h1 = 0xefcdab89;
-    hd->h2 = 0x98badcfe;
-    hd->h3 = 0x10325476;
-    hd->h4 = 0xc3d2e1f0;
-    hd->nblocks = 0;
-    hd->count = 0;
-}
-
-
-/****************
- * Transform the message X which consists of 16 32-bit-words
- */
-static void transform( SHA1_CONTEXT *hd, uint8_t *data )
-{
-    uint32_t a,b,c,d,e,tm;
-    uint32_t x[16];
-
-    /* get values from the chaining vars */
-    a = hd->h0;
-    b = hd->h1;
-    c = hd->h2;
-    d = hd->h3;
-    e = hd->h4;
-
-#ifdef BIG_ENDIAN_HOST
-    memcpy( x, data, 64 );
-#else
-    { int i;
-      uint8_t *p2;
-      for(i=0, p2=(unsigned char*)x; i < 16; i++, p2 += 4 ) {
-       p2[3] = *data++;
-       p2[2] = *data++;
-       p2[1] = *data++;
-       p2[0] = *data++;
-      }
-    }
-#endif
-
-
-#define K1  0x5A827999L
-#define K2  0x6ED9EBA1L
-#define K3  0x8F1BBCDCL
-#define K4  0xCA62C1D6L
-#define F1(x,y,z)   ( z ^ ( x & ( y ^ z ) ) )
-#define F2(x,y,z)   ( x ^ y ^ z )
-#define F3(x,y,z)   ( ( x & y ) | ( z & ( x | y ) ) )
-#define F4(x,y,z)   ( x ^ y ^ z )
-
-
-#define M(i) ( tm =   x[i&0x0f] ^ x[(i-14)&0x0f] \
-                   ^ x[(i-8)&0x0f] ^ x[(i-3)&0x0f] \
-              , (x[i&0x0f] = rol(tm,1)) )
-
-#define R(a,b,c,d,e,f,k,m)  do { e += rol( a, 5 )     \
-                                     + f( b, c, d )  \
-                                     + k             \
-                                     + m;            \
-                                b = rol( b, 30 );    \
-                              } while(0)
-    R( a, b, c, d, e, F1, K1, x[ 0] );
-    R( e, a, b, c, d, F1, K1, x[ 1] );
-    R( d, e, a, b, c, F1, K1, x[ 2] );
-    R( c, d, e, a, b, F1, K1, x[ 3] );
-    R( b, c, d, e, a, F1, K1, x[ 4] );
-    R( a, b, c, d, e, F1, K1, x[ 5] );
-    R( e, a, b, c, d, F1, K1, x[ 6] );
-    R( d, e, a, b, c, F1, K1, x[ 7] );
-    R( c, d, e, a, b, F1, K1, x[ 8] );
-    R( b, c, d, e, a, F1, K1, x[ 9] );
-    R( a, b, c, d, e, F1, K1, x[10] );
-    R( e, a, b, c, d, F1, K1, x[11] );
-    R( d, e, a, b, c, F1, K1, x[12] );
-    R( c, d, e, a, b, F1, K1, x[13] );
-    R( b, c, d, e, a, F1, K1, x[14] );
-    R( a, b, c, d, e, F1, K1, x[15] );
-    R( e, a, b, c, d, F1, K1, M(16) );
-    R( d, e, a, b, c, F1, K1, M(17) );
-    R( c, d, e, a, b, F1, K1, M(18) );
-    R( b, c, d, e, a, F1, K1, M(19) );
-    R( a, b, c, d, e, F2, K2, M(20) );
-    R( e, a, b, c, d, F2, K2, M(21) );
-    R( d, e, a, b, c, F2, K2, M(22) );
-    R( c, d, e, a, b, F2, K2, M(23) );
-    R( b, c, d, e, a, F2, K2, M(24) );
-    R( a, b, c, d, e, F2, K2, M(25) );
-    R( e, a, b, c, d, F2, K2, M(26) );
-    R( d, e, a, b, c, F2, K2, M(27) );
-    R( c, d, e, a, b, F2, K2, M(28) );
-    R( b, c, d, e, a, F2, K2, M(29) );
-    R( a, b, c, d, e, F2, K2, M(30) );
-    R( e, a, b, c, d, F2, K2, M(31) );
-    R( d, e, a, b, c, F2, K2, M(32) );
-    R( c, d, e, a, b, F2, K2, M(33) );
-    R( b, c, d, e, a, F2, K2, M(34) );
-    R( a, b, c, d, e, F2, K2, M(35) );
-    R( e, a, b, c, d, F2, K2, M(36) );
-    R( d, e, a, b, c, F2, K2, M(37) );
-    R( c, d, e, a, b, F2, K2, M(38) );
-    R( b, c, d, e, a, F2, K2, M(39) );
-    R( a, b, c, d, e, F3, K3, M(40) );
-    R( e, a, b, c, d, F3, K3, M(41) );
-    R( d, e, a, b, c, F3, K3, M(42) );
-    R( c, d, e, a, b, F3, K3, M(43) );
-    R( b, c, d, e, a, F3, K3, M(44) );
-    R( a, b, c, d, e, F3, K3, M(45) );
-    R( e, a, b, c, d, F3, K3, M(46) );
-    R( d, e, a, b, c, F3, K3, M(47) );
-    R( c, d, e, a, b, F3, K3, M(48) );
-    R( b, c, d, e, a, F3, K3, M(49) );
-    R( a, b, c, d, e, F3, K3, M(50) );
-    R( e, a, b, c, d, F3, K3, M(51) );
-    R( d, e, a, b, c, F3, K3, M(52) );
-    R( c, d, e, a, b, F3, K3, M(53) );
-    R( b, c, d, e, a, F3, K3, M(54) );
-    R( a, b, c, d, e, F3, K3, M(55) );
-    R( e, a, b, c, d, F3, K3, M(56) );
-    R( d, e, a, b, c, F3, K3, M(57) );
-    R( c, d, e, a, b, F3, K3, M(58) );
-    R( b, c, d, e, a, F3, K3, M(59) );
-    R( a, b, c, d, e, F4, K4, M(60) );
-    R( e, a, b, c, d, F4, K4, M(61) );
-    R( d, e, a, b, c, F4, K4, M(62) );
-    R( c, d, e, a, b, F4, K4, M(63) );
-    R( b, c, d, e, a, F4, K4, M(64) );
-    R( a, b, c, d, e, F4, K4, M(65) );
-    R( e, a, b, c, d, F4, K4, M(66) );
-    R( d, e, a, b, c, F4, K4, M(67) );
-    R( c, d, e, a, b, F4, K4, M(68) );
-    R( b, c, d, e, a, F4, K4, M(69) );
-    R( a, b, c, d, e, F4, K4, M(70) );
-    R( e, a, b, c, d, F4, K4, M(71) );
-    R( d, e, a, b, c, F4, K4, M(72) );
-    R( c, d, e, a, b, F4, K4, M(73) );
-    R( b, c, d, e, a, F4, K4, M(74) );
-    R( a, b, c, d, e, F4, K4, M(75) );
-    R( e, a, b, c, d, F4, K4, M(76) );
-    R( d, e, a, b, c, F4, K4, M(77) );
-    R( c, d, e, a, b, F4, K4, M(78) );
-    R( b, c, d, e, a, F4, K4, M(79) );
-
-    /* update chainig vars */
-    hd->h0 += a;
-    hd->h1 += b;
-    hd->h2 += c;
-    hd->h3 += d;
-    hd->h4 += e;
-}
-
-
-/* Update the message digest with the contents
- * of INBUF with length INLEN.
- */
-void sha1_write( SHA1_CONTEXT *hd, unsigned char *inbuf, size_t inlen)
-{
-
-    if( hd->count == 64 ) { /* flush the buffer */
-       transform( hd, hd->buf );
-       hd->count = 0;
-       hd->nblocks++;
-    }
-    if( !inbuf )
-       return;
-    if( hd->count ) {
-       for( ; inlen && hd->count < 64; inlen-- )
-           hd->buf[hd->count++] = *inbuf++;
-       sha1_write( hd, NULL, 0 );
-       if( !inlen )
-           return;
-    }
-
-    while( inlen >= 64 ) {
-       transform( hd, inbuf );
-       hd->count = 0;
-       hd->nblocks++;
-       inlen -= 64;
-       inbuf += 64;
-    }
-    for( ; inlen && hd->count < 64; inlen-- )
-       hd->buf[hd->count++] = *inbuf++;
-}
-
-
-/* The routine final terminates the computation and
- * returns the digest.
- * The handle is prepared for a new cycle, but adding uint8_ts to the
- * handle will the destroy the returned buffer.
- * Returns: 20 uint8_ts representing the digest.
- */
-
-void sha1_final(SHA1_CONTEXT *hd)
-{
-    unsigned int t, msb, lsb;
-    unsigned char *p;
-
-    sha1_write(hd, NULL, 0); /* flush */;
-
-    msb = 0;
-    t = hd->nblocks;
-    if( (lsb = t << 6) < t ) /* multiply by 64 to make a uint8_t count */
-       msb++;
-    msb += t >> 26;
-    t = lsb;
-    if( (lsb = t + hd->count) < t ) /* add the count */
-       msb++;
-    t = lsb;
-    if( (lsb = t << 3) < t ) /* multiply by 8 to make a bit count */
-       msb++;
-    msb += t >> 29;
-
-    if( hd->count < 56 ) { /* enough room */
-       hd->buf[hd->count++] = 0x80; /* pad */
-       while( hd->count < 56 )
-           hd->buf[hd->count++] = 0;  /* pad */
-    }
-    else { /* need one extra block */
-       hd->buf[hd->count++] = 0x80; /* pad character */
-       while( hd->count < 64 )
-           hd->buf[hd->count++] = 0;
-       sha1_write(hd, NULL, 0);  /* flush */;
-       memset(hd->buf, 0, 56 ); /* fill next block with zeroes */
-    }
-    /* append the 64 bit count */
-    hd->buf[56] = msb >> 24;
-    hd->buf[57] = msb >> 16;
-    hd->buf[58] = msb >>  8;
-    hd->buf[59] = msb     ;
-    hd->buf[60] = lsb >> 24;
-    hd->buf[61] = lsb >> 16;
-    hd->buf[62] = lsb >>  8;
-    hd->buf[63] = lsb     ;
-    transform( hd, hd->buf );
-
-    p = hd->buf;
-#ifdef BIG_ENDIAN_HOST
-#define X(a) do { *(uint32_t *)p = hd->h##a ; p += 4; } while(0)
-#else /* little endian */
-#define X(a) do { *p++ = hd->h##a >> 24; *p++ = hd->h##a >> 16;         \
-                     *p++ = hd->h##a >> 8; *p++ = hd->h##a; } while(0)
-#endif
-    X(0);
-    X(1);
-    X(2);
-    X(3);
-    X(4);
-#undef X
-
-}
-
-uint8_t *sha1_read( SHA1_CONTEXT *hd )
-{
-    return hd->buf;
-}
diff --git a/sha.h b/sha.h
deleted file mode 100644 (file)
index 3803c68..0000000
--- a/sha.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#ifndef __SHA_H__
-#define __SHA_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <inttypes.h>
-
-#include "bithelp.h"
-
-typedef struct {
-    uint32_t   h0,h1,h2,h3,h4;
-    uint32_t   nblocks;
-    uint8_t    buf[64];
-    int                count;
-} SHA1_CONTEXT;
-
-void sha1_init(SHA1_CONTEXT *);
-void sha1_write(SHA1_CONTEXT *, uint8_t *, size_t);
-void sha1_final(SHA1_CONTEXT *);
-unsigned char *sha1_read(SHA1_CONTEXT *);
-
-#endif /* __SHA_H__ */
diff --git a/sha1.c b/sha1.c
new file mode 100644 (file)
index 0000000..87cfb50
--- /dev/null
+++ b/sha1.c
@@ -0,0 +1,182 @@
+/*
+ SHA-1 in C
+
+ By Steve Reid <steve@edmweb.com>, with small changes to make it
+ fit into mutt by Thomas Roessler <roessler@does-not-exist.org>.
+
+ 100% Public Domain.
+
+ Test Vectors (from FIPS PUB 180-1)
+ "abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+ "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+ A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#define SHA1HANDSOFF
+
+#include <string.h>
+
+#include "sha1.h"
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifdef WORDS_BIGENDIAN
+#  define blk0(i) block->l[i]
+#else
+#  define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+                   |(rol(block->l[i],8)&0x00FF00FF))
+#endif
+
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+    ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
+{
+u_int32_t a, b, c, d, e;
+typedef union {
+    unsigned char c[64];
+    u_int32_t l[16];
+} CHAR64LONG16;
+#ifdef SHA1HANDSOFF
+CHAR64LONG16 block[1];  /* use array to appear as a pointer */
+    memcpy(block, buffer, 64);
+#else
+    /* The following had better never be used because it causes the
+     * pointer-to-const buffer to be cast into a pointer to non-const.
+     * And the result is written through.  I threw a "const" in, hoping
+     * this will cause a diagnostic.
+     */
+CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len)
+{
+u_int32_t i;
+u_int32_t j;
+
+    j = context->count[0];
+    if ((context->count[0] += len << 3) < j)
+       context->count[1]++;
+    context->count[1] += (len>>29);
+    j = (j >> 3) & 63;
+    if ((j + len) > 63) {
+        memcpy(&context->buffer[j], data, (i = 64-j));
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64) {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
+    }
+    else i = 0;
+    memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned i;
+unsigned char finalcount[8];
+unsigned char c;
+
+#if 0  /* untested "improvement" by DHR */
+    /* Convert context->count to a sequence of bytes
+     * in finalcount.  Second element first, but
+     * big-endian order within element.
+     * But we do it all backwards.
+     */
+    unsigned char *fcp = &finalcount[8];
+
+    for (i = 0; i < 2; i++)
+    {
+       u_int32_t t = context->count[i];
+       int j;
+
+       for (j = 0; j < 4; t >>= 8, j++)
+           *--fcp = (unsigned char) t
+    }
+#else
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+#endif
+    c = 0200;
+    SHA1Update(context, &c, 1);
+    while ((context->count[0] & 504) != 448) {
+       c = 0000;
+        SHA1Update(context, &c, 1);
+    }
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
+    for (i = 0; i < 20; i++) {
+        digest[i] = (unsigned char)
+         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+    }
+}
diff --git a/sha1.h b/sha1.h
new file mode 100644 (file)
index 0000000..ea0b4db
--- /dev/null
+++ b/sha1.h
@@ -0,0 +1,33 @@
+/*
+ SHA-1 in C
+
+ By Steve Reid <steve@edmweb.com>, with small changes to make it
+ fit into mutt by Thomas Roessler <roessler@does-not-exist.org>.
+
+*/
+
+#ifndef _SHA1_H
+# define _SHA1_H
+
+#include <sys/types.h>
+
+typedef struct {
+  u_int32_t state[5];
+  u_int32_t count[2];
+  unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+
+# define SHA1_Transform SHA1Transform
+# define SHA1_Init SHA1Init
+# define SHA1_Update SHA1Update
+# define SHA1_Final SHA1Final
+
+# define SHA_DIGEST_LENGTH 20
+
+#endif
+