]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Update.
authorSimon Josefsson <simon@josefsson.org>
Wed, 12 Oct 2005 13:36:53 +0000 (13:36 +0000)
committerSimon Josefsson <simon@josefsson.org>
Wed, 12 Oct 2005 13:36:53 +0000 (13:36 +0000)
23 files changed:
gl/Makefile.am
gl/gc-gnulib.c [new file with mode: 0644]
gl/gc-libgcrypt.c [new file with mode: 0644]
gl/gc-pbkdf2-sha1.c [new file with mode: 0644]
gl/gc.h [new file with mode: 0644]
gl/hmac-sha1.c [new file with mode: 0644]
gl/hmac.h [new file with mode: 0644]
gl/m4/gc-hmac-sha1.m4 [new file with mode: 0644]
gl/m4/gc-pbkdf2-sha1.m4 [new file with mode: 0644]
gl/m4/gc.m4 [new file with mode: 0644]
gl/m4/gnulib-cache.m4
gl/m4/gnulib-comp.m4
gl/m4/hmac-sha1.m4 [new file with mode: 0644]
gl/m4/inttypes.m4 [new file with mode: 0644]
gl/m4/memxor.m4 [new file with mode: 0644]
gl/m4/restrict.m4 [new file with mode: 0644]
gl/m4/sha1.m4 [new file with mode: 0644]
gl/m4/stdint.m4 [new file with mode: 0644]
gl/memxor.c [new file with mode: 0644]
gl/memxor.h [new file with mode: 0644]
gl/sha1.c [new file with mode: 0644]
gl/sha1.h [new file with mode: 0644]
gl/stdint_.h [new file with mode: 0644]

index 1e164be1bc109ff0162bbe441a98727f394ae9b6..6220ae0ee0ab6fa6d3888f3ff207014eef11817f 100644 (file)
@@ -8,7 +8,7 @@
 # the same distribution terms as the rest of that program.
 #
 # Generated by gnulib-tool.
-# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl getline getpass inet_ntop memmem memmove minmax readline snprintf socklen
+# Reproduce by: gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl gc-pbkdf2-sha1 getline getpass inet_ntop memmem memmove minmax readline snprintf socklen
 
 AUTOMAKE_OPTIONS = 1.5 gnits no-dependencies
 
@@ -38,6 +38,12 @@ MOSTLYCLEANFILES += alloca.h alloca.h-t
 
 ## end   gnulib module alloca-opt
 
+## begin gnulib module gc
+
+libgnu_la_LIBADD += $(LIBGCRYPT)
+
+## end   gnulib module gc
+
 ## begin gnulib module inet_ntop
 
 libgnu_la_SOURCES += inet_ntop.h
@@ -82,6 +88,20 @@ MOSTLYCLEANFILES += stdbool.h stdbool.h-t
 
 ## end   gnulib module stdbool
 
+## begin gnulib module stdint
+
+BUILT_SOURCES += $(STDINT_H)
+EXTRA_DIST += stdint_.h
+
+# We need the following in order to create <stdint.h> when the system
+# doesn't have one that works with the given compiler.
+stdint.h: stdint_.h
+       sed -e 's/@''HAVE_LONG_64BIT''@/$(HAVE_LONG_64BIT)/g;s/@''HAVE_LONG_LONG_64BIT@/$(HAVE_LONG_LONG_64BIT)/g' < $(srcdir)/stdint_.h > $@-t
+       mv $@-t $@
+MOSTLYCLEANFILES += stdint.h stdint.h-t
+
+## end   gnulib module stdint
+
 ## begin gnulib module vasnprintf
 
 libgnu_la_SOURCES += printf-args.h printf-parse.h vasnprintf.h
diff --git a/gl/gc-gnulib.c b/gl/gc-gnulib.c
new file mode 100644 (file)
index 0000000..9d6cfeb
--- /dev/null
@@ -0,0 +1,207 @@
+/* gc-gl-common.c --- Common gnulib internal crypto interface functions
+ * Copyright (C) 2002, 2003, 2004, 2005  Simon Josefsson
+ *
+ * This file 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, or (at your
+ * option) any later version.
+ *
+ * This file 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 Lesser General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/* Note: This file is only built if GC uses internal functions. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Get prototype. */
+#include <gc.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+/* For randomize. */
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef GC_USE_MD5
+# include "md5.h"
+#endif
+#ifdef GC_USE_SHA1
+# include "sha1.h"
+#endif
+#ifdef GC_USE_HMAC_MD5
+# include "hmac.h"
+#endif
+
+Gc_rc
+gc_init (void)
+{
+  return GC_OK;
+}
+
+void
+gc_done (void)
+{
+  return;
+}
+
+/* Randomness. */
+
+static Gc_rc
+randomize (int level, char *data, size_t datalen)
+{
+  int fd;
+  const char *device;
+  size_t len = 0;
+  int rc;
+
+  switch (level)
+    {
+    case 0:
+      device = NAME_OF_NONCE_DEVICE;
+      break;
+
+    case 1:
+      device = NAME_OF_PSEUDO_RANDOM_DEVICE;
+      break;
+
+    default:
+      device = NAME_OF_RANDOM_DEVICE;
+      break;
+    }
+
+  fd = open (device, O_RDONLY);
+  if (fd < 0)
+    return GC_RANDOM_ERROR;
+
+  do
+    {
+      ssize_t tmp;
+
+      tmp = read (fd, data, datalen);
+
+      if (tmp < 0)
+       {
+         int save_errno = errno;
+         close (fd);
+         errno = save_errno;
+         return GC_RANDOM_ERROR;
+       }
+
+      len += tmp;
+    }
+  while (len < datalen);
+
+  rc = close (fd);
+  if (rc < 0)
+    return GC_RANDOM_ERROR;
+
+  return GC_OK;
+}
+
+Gc_rc
+gc_nonce (char *data, size_t datalen)
+{
+  return randomize (0, data, datalen);
+}
+
+Gc_rc
+gc_pseudo_random (char *data, size_t datalen)
+{
+  return randomize (1, data, datalen);
+}
+
+Gc_rc
+gc_random (char *data, size_t datalen)
+{
+  return randomize (2, data, datalen);
+}
+
+/* Memory allocation. */
+
+void
+gc_set_allocators (gc_malloc_t func_malloc,
+                  gc_malloc_t secure_malloc,
+                  gc_secure_check_t secure_check,
+                  gc_realloc_t func_realloc, gc_free_t func_free)
+{
+  return;
+}
+
+/* Hashes. */
+
+Gc_rc
+gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
+{
+  switch (hash)
+    {
+#ifdef GC_USE_MD5
+    case GC_MD5:
+      md5_buffer (in, inlen, resbuf);
+      break;
+#endif
+
+#ifdef GC_USE_SHA1
+    case GC_SHA1:
+      sha1_buffer (in, inlen, resbuf);
+      break;
+#endif
+
+    default:
+      return GC_INVALID_HASH;
+    }
+
+  return GC_OK;
+}
+
+#ifdef GC_USE_MD5
+Gc_rc
+gc_md5 (const void *in, size_t inlen, void *resbuf)
+{
+  md5_buffer (in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_SHA1
+Gc_rc
+gc_sha1 (const void *in, size_t inlen, void *resbuf)
+{
+  sha1_buffer (in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_HMAC_MD5
+Gc_rc
+gc_hmac_md5 (const void *key, size_t keylen,
+            const void *in, size_t inlen, char *resbuf)
+{
+  hmac_md5 (key, keylen, in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_HMAC_SHA1
+Gc_rc
+gc_hmac_sha1 (const void *key, size_t keylen,
+             const void *in, size_t inlen, char *resbuf)
+{
+  hmac_sha1 (key, keylen, in, inlen, resbuf);
+  return GC_OK;
+}
+#endif
diff --git a/gl/gc-libgcrypt.c b/gl/gc-libgcrypt.c
new file mode 100644 (file)
index 0000000..6b985c9
--- /dev/null
@@ -0,0 +1,271 @@
+/* gc-libgcrypt.c --- Crypto wrappers around Libgcrypt for GC.
+ * Copyright (C) 2002, 2003, 2004, 2005  Simon Josefsson
+ *
+ * This file 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, or (at your
+ * option) any later version.
+ *
+ * This file 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 Lesser General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+/* Note: This file is only built if GC uses Libgcrypt. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+/* Get prototype. */
+#include "gc.h"
+
+/* Get libgcrypt API. */
+#include <gcrypt.h>
+
+#include <assert.h>
+
+/* Initialization. */
+
+Gc_rc
+gc_init (void)
+{
+  gcry_error_t err;
+
+  err = gcry_control (GCRYCTL_ANY_INITIALIZATION_P);
+  if (err == GPG_ERR_NO_ERROR)
+    {
+      if (gcry_check_version (GCRYPT_VERSION) == NULL)
+       return GC_INIT_ERROR;
+
+      err = gcry_control (GCRYCTL_INITIALIZATION_FINISHED, NULL, 0);
+      if (err != GPG_ERR_NO_ERROR)
+       return GC_INIT_ERROR;
+    }
+
+  return GC_OK;
+}
+
+void
+gc_done (void)
+{
+  return;
+}
+
+/* Randomness. */
+
+Gc_rc
+gc_nonce (char *data, size_t datalen)
+{
+  gcry_create_nonce ((unsigned char *) data, datalen);
+  return GC_OK;
+}
+
+Gc_rc
+gc_pseudo_random (char *data, size_t datalen)
+{
+  gcry_randomize ((unsigned char *) data, datalen, GCRY_STRONG_RANDOM);
+  return GC_OK;
+}
+
+Gc_rc
+gc_random (char *data, size_t datalen)
+{
+  gcry_randomize ((unsigned char *) data, datalen, GCRY_VERY_STRONG_RANDOM);
+  return GC_OK;
+}
+
+/* Memory allocation. */
+
+void
+gc_set_allocators (gc_malloc_t func_malloc,
+                  gc_malloc_t secure_malloc,
+                  gc_secure_check_t secure_check,
+                  gc_realloc_t func_realloc, gc_free_t func_free)
+{
+  gcry_set_allocation_handler (func_malloc, secure_malloc, secure_check,
+                              func_realloc, func_free);
+}
+
+/* Hashes. */
+
+Gc_rc
+gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *resbuf)
+{
+  int gcryalg;
+
+  switch (hash)
+    {
+#ifdef GC_USE_MD5
+    case GC_MD5:
+      gcryalg = GCRY_MD_MD5;
+      break;
+#endif
+
+#ifdef GC_USE_SHA1
+    case GC_SHA1:
+      gcryalg = GCRY_MD_SHA1;
+      break;
+#endif
+
+    default:
+      return GC_INVALID_HASH;
+    }
+
+  gcry_md_hash_buffer (gcryalg, resbuf, in, inlen);
+
+  return GC_OK;
+}
+
+/* One-call interface. */
+
+#ifdef GC_USE_MD5
+Gc_rc
+gc_md5 (const void *in, size_t inlen, void *resbuf)
+{
+  size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
+  gcry_md_hd_t hd;
+  gpg_error_t err;
+  unsigned char *p;
+
+  assert (outlen == GC_MD5_DIGEST_SIZE);
+
+  err = gcry_md_open (&hd, GCRY_MD_MD5, 0);
+  if (err != GPG_ERR_NO_ERROR)
+    return GC_INVALID_HASH;
+
+  gcry_md_write (hd, in, inlen);
+
+  p = gcry_md_read (hd, GCRY_MD_MD5);
+  if (p == NULL)
+    {
+      gcry_md_close (hd);
+      return GC_INVALID_HASH;
+    }
+
+  memcpy (resbuf, p, outlen);
+
+  gcry_md_close (hd);
+
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_SHA1
+Gc_rc
+gc_sha1 (const void *in, size_t inlen, void *resbuf)
+{
+  size_t outlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
+  gcry_md_hd_t hd;
+  gpg_error_t err;
+  unsigned char *p;
+
+  assert (outlen == GC_SHA1_DIGEST_SIZE);
+
+  err = gcry_md_open (&hd, GCRY_MD_SHA1, 0);
+  if (err != GPG_ERR_NO_ERROR)
+    return GC_INVALID_HASH;
+
+  gcry_md_write (hd, in, inlen);
+
+  p = gcry_md_read (hd, GCRY_MD_SHA1);
+  if (p == NULL)
+    {
+      gcry_md_close (hd);
+      return GC_INVALID_HASH;
+    }
+
+  memcpy (resbuf, p, outlen);
+
+  gcry_md_close (hd);
+
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_HMAC_MD5
+Gc_rc
+gc_hmac_md5 (const void *key, size_t keylen,
+            const void *in, size_t inlen, char *resbuf)
+{
+  size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_MD5);
+  gcry_md_hd_t mdh;
+  unsigned char *hash;
+  gpg_error_t err;
+
+  assert (hlen == 16);
+
+  err = gcry_md_open (&mdh, GCRY_MD_MD5, GCRY_MD_FLAG_HMAC);
+  if (err != GPG_ERR_NO_ERROR)
+    return GC_INVALID_HASH;
+
+  err = gcry_md_setkey (mdh, key, keylen);
+  if (err != GPG_ERR_NO_ERROR)
+    {
+      gcry_md_close (mdh);
+      return GC_INVALID_HASH;
+    }
+
+  gcry_md_write (mdh, in, inlen);
+
+  hash = gcry_md_read (mdh, GCRY_MD_MD5);
+  if (hash == NULL)
+    {
+      gcry_md_close (mdh);
+      return GC_INVALID_HASH;
+    }
+
+  memcpy (resbuf, hash, hlen);
+
+  gcry_md_close (mdh);
+
+  return GC_OK;
+}
+#endif
+
+#ifdef GC_USE_HMAC_SHA1
+Gc_rc
+gc_hmac_sha1 (const void *key, size_t keylen,
+             const void *in, size_t inlen, char *resbuf)
+{
+  size_t hlen = gcry_md_get_algo_dlen (GCRY_MD_SHA1);
+  gcry_md_hd_t mdh;
+  unsigned char *hash;
+  gpg_error_t err;
+
+  assert (hlen == 16);
+
+  err = gcry_md_open (&mdh, GCRY_MD_SHA1, GCRY_MD_FLAG_HMAC);
+  if (err != GPG_ERR_NO_ERROR)
+    return GC_INVALID_HASH;
+
+  err = gcry_md_setkey (mdh, key, keylen);
+  if (err != GPG_ERR_NO_ERROR)
+    {
+      gcry_md_close (mdh);
+      return GC_INVALID_HASH;
+    }
+
+  gcry_md_write (mdh, in, inlen);
+
+  hash = gcry_md_read (mdh, GCRY_MD_SHA1);
+  if (hash == NULL)
+    {
+      gcry_md_close (mdh);
+      return GC_INVALID_HASH;
+    }
+
+  memcpy (resbuf, hash, hlen);
+
+  gcry_md_close (mdh);
+
+  return GC_OK;
+}
+#endif
diff --git a/gl/gc-pbkdf2-sha1.c b/gl/gc-pbkdf2-sha1.c
new file mode 100644 (file)
index 0000000..0317b3a
--- /dev/null
@@ -0,0 +1,187 @@
+/* gc-pbkdf2-sha1.c --- Password-Based Key Derivation Function a'la PKCS#5
+   Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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.  The comments in this file are taken
+   from RFC 2898.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "gc.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * 5.2 PBKDF2
+ *
+ *  PBKDF2 applies a pseudorandom function (see Appendix B.1 for an
+ *  example) to derive keys. The length of the derived key is essentially
+ *  unbounded. (However, the maximum effective search space for the
+ *  derived key may be limited by the structure of the underlying
+ *  pseudorandom function. See Appendix B.1 for further discussion.)
+ *  PBKDF2 is recommended for new applications.
+ *
+ *  PBKDF2 (P, S, c, dkLen)
+ *
+ *  Options:        PRF        underlying pseudorandom function (hLen
+ *                             denotes the length in octets of the
+ *                             pseudorandom function output)
+ *
+ *  Input:          P          password, an octet string (ASCII or UTF-8)
+ *                  S          salt, an octet string
+ *                  c          iteration count, a positive integer
+ *                  dkLen      intended length in octets of the derived
+ *                             key, a positive integer, at most
+ *                             (2^32 - 1) * hLen
+ *
+ *  Output:         DK         derived key, a dkLen-octet string
+ */
+
+Gc_rc
+gc_pbkdf2_sha1 (const char *P, size_t Plen,
+               const char *S, size_t Slen,
+               unsigned int c,
+               char *DK, size_t dkLen)
+{
+  unsigned int hLen = 20;
+  char U[20];
+  char T[20];
+  unsigned int u;
+  unsigned int l;
+  unsigned int r;
+  unsigned int i;
+  unsigned int k;
+  int rc;
+
+  if (c == 0)
+    return GC_PKCS5_INVALID_ITERATION_COUNT;
+
+  if (dkLen == 0)
+    return GC_PKCS5_INVALID_DERIVED_KEY_LENGTH;
+
+  /*
+   *
+   *  Steps:
+   *
+   *     1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and
+   *        stop.
+   */
+
+  if (dkLen > 4294967295U)
+    return GC_PKCS5_DERIVED_KEY_TOO_LONG;
+
+  /*
+   *     2. Let l be the number of hLen-octet blocks in the derived key,
+   *        rounding up, and let r be the number of octets in the last
+   *        block:
+   *
+   *                  l = CEIL (dkLen / hLen) ,
+   *                  r = dkLen - (l - 1) * hLen .
+   *
+   *        Here, CEIL (x) is the "ceiling" function, i.e. the smallest
+   *        integer greater than, or equal to, x.
+   */
+
+  l = dkLen / hLen;
+  if (dkLen % hLen)
+    l++;
+  r = dkLen - (l - 1) * hLen;
+
+  /*
+   *     3. For each block of the derived key apply the function F defined
+   *        below to the password P, the salt S, the iteration count c, and
+   *        the block index to compute the block:
+   *
+   *                  T_1 = F (P, S, c, 1) ,
+   *                  T_2 = F (P, S, c, 2) ,
+   *                  ...
+   *                  T_l = F (P, S, c, l) ,
+   *
+   *        where the function F is defined as the exclusive-or sum of the
+   *        first c iterates of the underlying pseudorandom function PRF
+   *        applied to the password P and the concatenation of the salt S
+   *        and the block index i:
+   *
+   *                  F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c
+   *
+   *        where
+   *
+   *                  U_1 = PRF (P, S || INT (i)) ,
+   *                  U_2 = PRF (P, U_1) ,
+   *                  ...
+   *                  U_c = PRF (P, U_{c-1}) .
+   *
+   *        Here, INT (i) is a four-octet encoding of the integer i, most
+   *        significant octet first.
+   *
+   *     4. Concatenate the blocks and extract the first dkLen octets to
+   *        produce a derived key DK:
+   *
+   *                  DK = T_1 || T_2 ||  ...  || T_l<0..r-1>
+   *
+   *     5. Output the derived key DK.
+   *
+   *  Note. The construction of the function F follows a "belt-and-
+   *  suspenders" approach. The iterates U_i are computed recursively to
+   *  remove a degree of parallelism from an opponent; they are exclusive-
+   *  ored together to reduce concerns about the recursion degenerating
+   *  into a small set of values.
+   *
+   */
+
+  for (i = 1; i <= l; i++)
+    {
+      memset (T, 0, hLen);
+
+      for (u = 1; u <= c; u++)
+       {
+         if (u == 1)
+           {
+             char *tmp;
+             size_t tmplen = Slen + 4;
+
+             tmp = malloc (tmplen);
+             if (tmp == NULL)
+               return GC_MALLOC_ERROR;
+
+             memcpy (tmp, S, Slen);
+             tmp[Slen + 0] = (i & 0xff000000) >> 24;
+             tmp[Slen + 1] = (i & 0x00ff0000) >> 16;
+             tmp[Slen + 2] = (i & 0x0000ff00) >> 8;
+             tmp[Slen + 3] = (i & 0x000000ff) >> 0;
+
+             rc = gc_hmac_sha1 (P, Plen, tmp, tmplen, U);
+
+             free (tmp);
+           }
+         else
+           rc = gc_hmac_sha1 (P, Plen, U, hLen, U);
+
+         if (rc != GC_OK)
+           return rc;
+
+         for (k = 0; k < hLen; k++)
+           T[k] ^= U[k];
+       }
+
+      memcpy (DK + (i - 1) * hLen, T, i == l ? r : hLen);
+    }
+
+  return GC_OK;
+}
diff --git a/gl/gc.h b/gl/gc.h
new file mode 100644 (file)
index 0000000..3a000ba
--- /dev/null
+++ b/gl/gc.h
@@ -0,0 +1,241 @@
+/* gc.h --- Header file for implementation agnostic crypto wrapper API.
+ * Copyright (C) 2002, 2003, 2004, 2005  Simon Josefsson
+ *
+ * This file 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, or (at your
+ * option) any later version.
+ *
+ * This file 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 Lesser General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef GC_H
+# define GC_H
+
+/* Get size_t. */
+# include <stddef.h>
+
+enum Gc_rc
+  {
+    GC_OK = 0,
+    GC_MALLOC_ERROR,
+    GC_INIT_ERROR,
+    GC_RANDOM_ERROR,
+    GC_INVALID_CIPHER,
+    GC_INVALID_HASH,
+    GC_PKCS5_INVALID_ITERATION_COUNT,
+    GC_PKCS5_INVALID_DERIVED_KEY_LENGTH,
+    GC_PKCS5_DERIVED_KEY_TOO_LONG
+  };
+typedef enum Gc_rc Gc_rc;
+
+/* Hash types. */
+enum Gc_hash
+  {
+    GC_MD5,
+    GC_SHA1
+  };
+typedef enum Gc_hash Gc_hash;
+
+#define GC_MD5_DIGEST_SIZE 16
+#define GC_SHA1_DIGEST_SIZE 20
+
+/* Call before respectively after any other functions. */
+extern Gc_rc gc_init (void);
+extern void gc_done (void);
+
+/* Memory allocation (avoid). */
+typedef void *(*gc_malloc_t) (size_t n);
+typedef int (*gc_secure_check_t) (const void *);
+typedef void *(*gc_realloc_t) (void *p, size_t n);
+typedef void (*gc_free_t) (void *);
+extern void gc_set_allocators (gc_malloc_t func_malloc,
+                              gc_malloc_t secure_malloc,
+                              gc_secure_check_t secure_check,
+                              gc_realloc_t func_realloc,
+                              gc_free_t func_free);
+
+/* Hashes. */
+
+/* Compute a hash value over buffer IN of INLEN bytes size using the
+   algorithm HASH, placing the result in the pre-allocated buffer OUT.
+   The required size of OUT depends on HASH, and is generally
+   GC_<HASH>_DIGEST_SIZE.  For example, for GC_MD5 the output buffer
+   must be 16 bytes.  The return value is 0 (GC_OK) on success, or
+   another Gc_rc error code. */
+extern Gc_rc
+gc_hash_buffer (Gc_hash hash, const void *in, size_t inlen, char *out);
+
+/* One-call interface. */
+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,
+                         const void *in, size_t inlen,
+                         char *resbuf);
+extern Gc_rc gc_hmac_sha1 (const void *key, size_t keylen,
+                          const void *in, size_t inlen,
+                          char *resbuf);
+
+/* Derive cryptographic keys from a password P of length PLEN, with
+   salt S of length SLEN, placing the result in pre-allocated buffer
+   DK of length DKLEN.  An iteration count is specified in C, where a
+   larger value means this function take more time (typical iteration
+   counts are 1000-20000).  This function "stretches" the key to be
+   exactly dkLen bytes long.  GC_OK is returned on success, otherwise
+   an Gc_rc error code is returned.  */
+extern Gc_rc
+gc_pbkdf2_sha1 (const char *P, size_t Plen,
+               const char *S, size_t Slen,
+               unsigned int c,
+               char *DK, size_t dkLen);
+
+/*
+  TODO:
+
+  From: Simon Josefsson <jas@extundo.com>
+  Subject: Re: generic crypto
+  Newsgroups: gmane.comp.lib.gnulib.bugs
+  Cc: bug-gnulib@gnu.org
+  Date: Fri, 07 Oct 2005 12:50:57 +0200
+  Mail-Copies-To: nobody
+
+  Paul Eggert <eggert@CS.UCLA.EDU> writes:
+
+  > Simon Josefsson <jas@extundo.com> writes:
+  >
+  >> * Perhaps the /dev/*random reading should be separated into a separate
+  >>   module?  It might be useful outside of the gc layer too.
+  >
+  > Absolutely.  I've been meaning to do that for months (for a "shuffle"
+  > program I want to add to coreutils), but hadn't gotten around to it.
+  > It would have to be generalized a bit.  I'd like to have the file
+  > descriptor cached, for example.
+
+  I'll write a separate module for that part.
+
+  I think we should even add a good PRNG that is re-seeded from
+  /dev/*random frequently.  GnuTLS can need a lot of random data on a
+  big server, more than /dev/random can supply.  And /dev/urandom might
+  not be strong enough.  Further, the security of /dev/*random can also
+  be questionable.
+
+  >>   I'm also not sure about the names of those functions, they suggest
+  >>   a more higher-level API than what is really offered (i.e., the
+  >>   names "nonce" and "pseudo_random" and "random" imply certain
+  >>   cryptographic properties).
+  >
+  > Could you expand a bit more on that?  What is the relationship between
+  > nonce/pseudorandom/random and the /dev/ values you are using?
+
+  There is none, that is the problem.
+
+  Applications generally need different kind of "random" numbers.
+  Sometimes they just need some random data and doesn't care whether it
+  is possible for an attacker to compute the string (aka a "nonce").
+  Sometimes they need data that is very difficult to compute (i.e.,
+  computing it require inverting SHA1 or similar).  Sometimes they need
+  data that is not possible to compute, i.e., it wants real entropy
+  collected over time on the system.  Collecting the last kind of random
+  data is very expensive, so it must not be used too often.  The second
+  kind of random data ("pseudo random") is typically generated by
+  seeding a good PRNG with a couple of hundred bytes of real entropy
+  from the "real random" data pool.  The "nonce" is usually computed
+  using the PRNG as well, because PRNGs are usually fast.
+
+  Pseudo-random data is typically used for session keys.  Strong random
+  data is often used to generate long-term keys (e.g., private RSA
+  keys).
+
+  Of course, there are many subtleties.  There are several different
+  kind of nonce:s.  Sometimes a nonce is just an ever-increasing
+  integer, starting from 0.  Sometimes it is assumed to be unlikely to
+  be the same as previous nonces, but without a requirement that the
+  nonce is possible to guess.  MD5(system clock) would thus suffice, if
+  it isn't called too often.  You can guess what the next value will be,
+  but it will always be different.
+
+  The problem is that /dev/*random doesn't offer any kind of semantic
+  guarantees.  But applications need an API that make that promise.
+
+  I think we should do this in several steps:
+
+  1) Write a module that can read from /dev/*random.
+
+  2) Add a module for a known-good PRNG suitable for random number
+  generation, that can be continuously re-seeded.
+
+  3) Add a high-level module that provide various different randomness
+  functions.  One for nonces, perhaps even different kind of nonces,
+  one for pseudo random data, and one for strong random data.  It is
+  not clear whether we can hope to achieve the last one in a portable
+  way.
+
+  Further, it would be useful to allow users to provide their own
+  entropy source as a file, used to seed the PRNG or initialize the
+  strong randomness pool.  This is used on embedded platforms that
+  doesn't have enough interrupts to hope to generate good random data.
+
+  > For example, why not use OpenBSD's /dev/arandom?
+
+  I don't trust ARC4.  For example, recent cryptographic efforts
+  indicate that you must throw away the first 512 bytes generated from
+  the PRNG for it to be secure.  I don't know whether OpenBSD do this.
+  Further, I recall some eprint paper on RC4 security that didn't
+  inspire confidence.
+
+  While I trust the random devices in OpenBSD more than
+  Solaris/AIX/HPUX/etc, I think that since we need something better on
+  Solaris/AIX/HPUX we'd might as well use it on OpenBSD or even Linux
+  too.
+
+  > Here is one thought.  The user could specify a desired quality level
+  > range, and the implementation then would supply random data that is at
+  > least as good as the lower bound of the range.  I.e., ihe
+  > implementation refuses to produce any random data if it can't generate
+  > data that is at least as good as the lower end of the range.  The
+  > upper bound of the range is advice from the user not to be any more
+  > expensive than that, but the implementation can ignore the advice if
+  > it doesn't have anything cheaper.
+
+  I'm not sure this is a good idea.  Users can't really be expected to
+  understand this.  Further, applications need many different kind of
+  random data.  Selecting the randomness level for each by the user will
+  be too complicated.
+
+  I think it is better if the application decide, from its cryptographic
+  requirement, what entropy quality it require, and call the proper API.
+  Meeting the implied semantic properties should be the job for gnulib.
+
+  >> Perhaps gc_dev_random and gc_dev_urandom?
+  >
+  > To some extent.  I'd rather insulate the user from the details of
+  > where the random numbers come from.  On the other hand we need to
+  > provide a way for applications to specify a file that contains
+  > random bits, so that people can override the defaults.
+
+  Agreed.
+
+  This may require some thinking before it is finalized.  Is it ok to
+  install the GC module as-is meanwhile?  Then I can continue to add the
+  stuff that GnuTLS need, and then come back to re-working the
+  randomness module.  That way, we have two different projects that use
+  the code.  GnuTLS includes the same randomness code that was in GNU
+  SASL and that is in the current gc module.  I feel much more
+  comfortable working in small steps at a time, rather then working on
+  this for a long time in gnulib and only later integrate the stuff in
+  GnuTLS.
+
+  Thanks,
+  Simon
+ */
+
+#endif /* GC_H */
diff --git a/gl/hmac-sha1.c b/gl/hmac-sha1.c
new file mode 100644 (file)
index 0000000..4ebcb59
--- /dev/null
@@ -0,0 +1,76 @@
+/* hmac-sha1.c -- hashed message authentication codes
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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 "hmac.h"
+
+#include "sha1.h"
+
+#include <string.h>
+
+#define IPAD 0x36
+#define OPAD 0x5c
+
+int
+hmac_sha1 (const void *key, size_t keylen,
+          const void *in, size_t inlen, void *resbuf)
+{
+  struct sha1_ctx inner;
+  struct sha1_ctx outer;
+  char optkeybuf[20];
+  char block[64];
+  char innerhash[20];
+
+  if (keylen > 64)
+    {
+      struct sha1_ctx keyhash;
+
+      sha1_init_ctx (&keyhash);
+      sha1_process_bytes (key, keylen, &keyhash);
+      sha1_finish_ctx (&keyhash, optkeybuf);
+
+      key = optkeybuf;
+      keylen = 20;
+    }
+
+  sha1_init_ctx (&inner);
+
+  memset (block, IPAD, sizeof (block));
+  memxor (block, key, keylen);
+
+  sha1_process_block (block, 64, &inner);
+  sha1_process_bytes (in, inlen, &inner);
+
+  sha1_finish_ctx (&inner, innerhash);
+
+  sha1_init_ctx (&outer);
+
+  memset (block, OPAD, sizeof (block));
+  memxor (block, key, keylen);
+
+  sha1_process_block (block, 64, &outer);
+  sha1_process_bytes (innerhash, 20, &outer);
+
+  sha1_finish_ctx (&outer, resbuf);
+
+  return 0;
+}
diff --git a/gl/hmac.h b/gl/hmac.h
new file mode 100644 (file)
index 0000000..5965b60
--- /dev/null
+++ b/gl/hmac.h
@@ -0,0 +1,41 @@
+/* hmac.h -- hashed message authentication codes
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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.  */
+
+#ifndef HMAC_H
+# define HMAC_H 1
+
+#include <stddef.h>
+
+/* Compute Hashed Message Authentication Code with MD5, as described
+   in RFC 2104, over BUFFER data of BUFLEN bytes using the KEY of
+   KEYLEN bytes, writing the output to pre-allocated 16 byte minimum
+   RESBUF buffer.  Return 0 on success.  */
+int
+hmac_md5 (const void *key, size_t keylen,
+         const void *buffer, size_t buflen, void *resbuf);
+
+/* Compute Hashed Message Authentication Code with SHA-1, over BUFFER
+   data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the
+   output to pre-allocated 20 byte minimum RESBUF buffer.  Return 0 on
+   success.  */
+int
+hmac_sha1 (const void *key, size_t keylen,
+          const void *in, size_t inlen, void *resbuf);
+
+#endif /* HMAC_H */
diff --git a/gl/m4/gc-hmac-sha1.m4 b/gl/m4/gc-hmac-sha1.m4
new file mode 100644 (file)
index 0000000..b6a3fa4
--- /dev/null
@@ -0,0 +1,17 @@
+# gc-hmac-sha1.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_HMAC_SHA1],
+[
+  AC_REQUIRE([gl_GC])
+  AC_DEFINE(GC_USE_HMAC_SHA1, 1,
+    [Define to if you want to support HMAC-SHA1 through GC.])
+  if test "$ac_cv_libgcrypt" != yes; then
+    gl_SHA1
+    gl_HMAC_SHA1
+    gl_MEMXOR
+  fi
+])
diff --git a/gl/m4/gc-pbkdf2-sha1.m4 b/gl/m4/gc-pbkdf2-sha1.m4
new file mode 100644 (file)
index 0000000..674f739
--- /dev/null
@@ -0,0 +1,11 @@
+# gc-pbkdf2-sha1.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_PBKDF2_SHA1],
+[
+  AC_LIBSOURCES([gc-pbkdf2-sha1.c])
+  AC_LIBOBJ([gc-pbkdf2-sha1])
+])
diff --git a/gl/m4/gc.m4 b/gl/m4/gc.m4
new file mode 100644 (file)
index 0000000..bf46b92
--- /dev/null
@@ -0,0 +1,99 @@
+# gc.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],
+[
+  AC_LIBSOURCES([gc.h, gc-gnulib.c, gc-libgcrypt.c])
+  AC_ARG_WITH(libgcrypt,
+    AS_HELP_STRING([--with-libgcrypt], [use libgcrypt for low-level crypto]),
+    libgcrypt=$withval, libgcrypt=no)
+  if test "$libgcrypt" != no; then
+    AC_LIB_HAVE_LINKFLAGS([gcrypt])
+  fi
+  if test "$ac_cv_libgcrypt" = yes; then
+    AC_CHECK_HEADER(gcrypt.h)
+    AC_LIBOBJ([gc-libgcrypt])
+  else
+    AC_LIBOBJ([gc-gnulib])
+
+    # Devices with randomness.
+    # FIXME: Are these the best defaults?
+
+    case "${target}" in
+      *-openbsd*)
+       NAME_OF_RANDOM_DEVICE="/dev/srandom"
+       NAME_OF_PSEUDO_RANDOM_DEVICE="/dev/prandom"
+       NAME_OF_NONCE_DEVICE="/dev/urandom"
+          ;;
+  
+      *-netbsd*)
+       NAME_OF_RANDOM_DEVICE="/dev/srandom"
+       NAME_OF_PSEUDO_RANDOM_DEVICE="/dev/urandom"
+       NAME_OF_NONCE_DEVICE="/dev/urandom"
+          ;;
+  
+      *-solaris* | *-irix* | *-dec-osf* )
+       NAME_OF_RANDOM_DEVICE="/dev/random"
+       NAME_OF_PSEUDO_RANDOM_DEVICE="/dev/random"
+       NAME_OF_NONCE_DEVICE="/dev/random"
+          ;;
+  
+      *)
+       NAME_OF_RANDOM_DEVICE="/dev/random"
+       NAME_OF_PSEUDO_RANDOM_DEVICE="/dev/urandom"
+       NAME_OF_NONCE_DEVICE="/dev/urandom"
+          ;;
+    esac
+  
+    AC_MSG_CHECKING([device with (strong) random data...])
+    AC_ARG_ENABLE(random-device,
+       AC_HELP_STRING([--enable-random-device],
+               [device with (strong) randomness (for Nettle)]),
+       NAME_OF_RANDOM_DEVICE=$enableval)
+    AC_MSG_RESULT($NAME_OF_RANDOM_DEVICE)
+  
+    AC_MSG_CHECKING([device with pseudo random data...])
+    AC_ARG_ENABLE(pseudo-random-device,
+       AC_HELP_STRING([--enable-pseudo-random-device],
+               [device with pseudo randomness (for Nettle)]),
+       NAME_OF_PSEUDO_RANDOM_DEVICE=$enableval)
+    AC_MSG_RESULT($NAME_OF_PSEUDO_RANDOM_DEVICE)
+  
+    AC_MSG_CHECKING([device with unpredictable data for nonces...])
+    AC_ARG_ENABLE(nonce-device,
+       AC_HELP_STRING([--enable-nonce-device],
+               [device with unpredictable nonces (for Nettle)]),
+       NAME_OF_NONCE_DEVICE=$enableval)
+    AC_MSG_RESULT($NAME_OF_NONCE_DEVICE)
+  
+    if test "$cross_compiling" != yes; then
+      AC_CHECK_FILE($NAME_OF_RANDOM_DEVICE,, AC_MSG_ERROR([[
+        *** Device for (strong) random data $NAME_OF_RANDOM_DEVICE does not exist
+      ]]))
+      AC_CHECK_FILE($NAME_OF_PSEUDO_RANDOM_DEVICE,, AC_MSG_ERROR([[
+        *** Device for pseudo-random data $NAME_OF_PSEUDO_RANDOM_DEVICE does not exist
+      ]]))
+      AC_CHECK_FILE($NAME_OF_NONCE_DEVICE,, AC_MSG_ERROR([[
+        *** Device for unpredictable nonces $NAME_OF_NONCE_DEVICE does not exist
+      ]]))
+    else
+      AC_MSG_NOTICE([[Cross compiling, assuming random devices exists...]])  
+    fi
+  
+    # FIXME: Open+read 42 bytes+close twice and compare data.  Should differ.
+  
+    AC_DEFINE_UNQUOTED(NAME_OF_RANDOM_DEVICE, "$NAME_OF_RANDOM_DEVICE",
+                     [defined to the name of the (strong) random device])
+    AC_DEFINE_UNQUOTED(NAME_OF_PSEUDO_RANDOM_DEVICE,
+                        "$NAME_OF_PSEUDO_RANDOM_DEVICE",
+                     [defined to the name of the pseudo random device])
+    AC_DEFINE_UNQUOTED(NAME_OF_NONCE_DEVICE, "$NAME_OF_NONCE_DEVICE",
+                     [defined to the name of the unpredictable nonce device])
+  fi
+])
+
+# Prerequisites of lib/gc.h
+AC_DEFUN([gl_PREREQ_GC], [:])
index 3c9d09e5ef6c8899fd77f9a06c0f7ccf8fff03cd..1801f66b4b5d22d3d85d819dca976fa7e1d69b28 100644 (file)
 
 
 # Specification in the form of a command-line invocation:
-#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl getline getpass inet_ntop memmem memmove minmax readline snprintf socklen
+#   gnulib-tool --import --dir=. --lib=libgnu --source-base=gl --m4-base=gl/m4 --aux-dir=. --lgpl --libtool --macro-prefix=gl gc-pbkdf2-sha1 getline getpass inet_ntop memmem memmove minmax readline snprintf socklen
 
 # Specification in the form of a few gnulib-tool.m4 macro invocations:
-gl_MODULES([getline getpass inet_ntop memmem memmove minmax readline snprintf socklen])
+gl_MODULES([gc-pbkdf2-sha1 getline getpass inet_ntop memmem memmove minmax readline snprintf socklen])
 gl_AVOID([])
 gl_SOURCE_BASE([gl])
 gl_M4_BASE([gl/m4])
index 74de8b6f093411f83f57dcd0799888d16a8d88db..dc37674189b202522f757b48180f30e85a75faa1 100644 (file)
@@ -26,6 +26,9 @@ AC_DEFUN([gl_EARLY],
 AC_DEFUN([gl_INIT],
 [
   gl_FUNC_ALLOCA
+  gl_GC
+  gl_GC_HMAC_SHA1
+  gl_GC_PBKDF2_SHA1
   gl_FUNC_GETDELIM
   gl_FUNC_GETLINE
   gl_FUNC_GETPASS
@@ -34,10 +37,12 @@ AC_DEFUN([gl_INIT],
   gl_FUNC_MEMMOVE
   gl_MINMAX
   gl_FUNC_READLINE
+  gl_C_RESTRICT
   gl_SIZE_MAX
   gl_FUNC_SNPRINTF
   gl_SOCKLEN_T
   AM_STDBOOL_H
+  gl_STDINT_H
   gl_FUNC_VASNPRINTF
   gl_XSIZE
 ])
@@ -48,17 +53,25 @@ AC_DEFUN([gl_FILE_LIST], [
   build-aux/config.rpath
   lib/alloca_.h
   lib/asnprintf.c
+  lib/gc-gnulib.c
+  lib/gc-libgcrypt.c
+  lib/gc-pbkdf2-sha1.c
+  lib/gc.h
   lib/getdelim.c
   lib/getdelim.h
   lib/getline.c
   lib/getline.h
   lib/getpass.c
   lib/getpass.h
+  lib/hmac-sha1.c
+  lib/hmac.h
   lib/inet_ntop.c
   lib/inet_ntop.h
   lib/memmem.c
   lib/memmem.h
   lib/memmove.c
+  lib/memxor.c
+  lib/memxor.h
   lib/minmax.h
   lib/printf-args.c
   lib/printf-args.h
@@ -66,20 +79,28 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/printf-parse.h
   lib/readline.c
   lib/readline.h
+  lib/sha1.c
+  lib/sha1.h
   lib/size_max.h
   lib/snprintf.c
   lib/snprintf.h
   lib/stdbool_.h
+  lib/stdint_.h
   lib/vasnprintf.c
   lib/vasnprintf.h
   lib/xsize.h
   m4/alloca.m4
   m4/eoverflow.m4
+  m4/gc-hmac-sha1.m4
+  m4/gc-pbkdf2-sha1.m4
+  m4/gc.m4
   m4/getdelim.m4
   m4/getline.m4
   m4/getpass.m4
+  m4/hmac-sha1.m4
   m4/inet_ntop.m4
   m4/intmax_t.m4
+  m4/inttypes.m4
   m4/inttypes_h.m4
   m4/lib-ld.m4
   m4/lib-link.m4
@@ -88,15 +109,19 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/longlong.m4
   m4/memmem.m4
   m4/memmove.m4
+  m4/memxor.m4
   m4/minmax.m4
   m4/onceonly_2_57.m4
   m4/readline.m4
+  m4/restrict.m4
+  m4/sha1.m4
   m4/signed.m4
   m4/size_max.m4
   m4/snprintf.m4
   m4/socklen.m4
   m4/sockpfaf.m4
   m4/stdbool.m4
+  m4/stdint.m4
   m4/stdint_h.m4
   m4/vasnprintf.m4
   m4/wchar_t.m4
diff --git a/gl/m4/hmac-sha1.m4 b/gl/m4/hmac-sha1.m4
new file mode 100644 (file)
index 0000000..1e95822
--- /dev/null
@@ -0,0 +1,11 @@
+# hmac-sha1.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_HMAC_SHA1],
+[
+  AC_LIBSOURCES([hmac.h, hmac-sha1.c])
+  AC_LIBOBJ([hmac-sha1])
+])
diff --git a/gl/m4/inttypes.m4 b/gl/m4/inttypes.m4
new file mode 100644 (file)
index 0000000..779bcea
--- /dev/null
@@ -0,0 +1,25 @@
+# inttypes.m4 serial 1 (gettext-0.11.4)
+dnl Copyright (C) 1997-2002 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.
+
+dnl From Paul Eggert.
+
+# Define HAVE_INTTYPES_H if <inttypes.h> exists and doesn't clash with
+# <sys/types.h>.
+
+AC_DEFUN([gt_HEADER_INTTYPES_H],
+[
+  AC_CACHE_CHECK([for inttypes.h], gt_cv_header_inttypes_h,
+  [
+    AC_TRY_COMPILE(
+      [#include <sys/types.h>
+#include <inttypes.h>],
+      [], gt_cv_header_inttypes_h=yes, gt_cv_header_inttypes_h=no)
+  ])
+  if test $gt_cv_header_inttypes_h = yes; then
+    AC_DEFINE_UNQUOTED(HAVE_INTTYPES_H, 1,
+      [Define if <inttypes.h> exists and doesn't clash with <sys/types.h>.])
+  fi
+])
diff --git a/gl/m4/memxor.m4 b/gl/m4/memxor.m4
new file mode 100644 (file)
index 0000000..96764cf
--- /dev/null
@@ -0,0 +1,11 @@
+# memxor.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_MEMXOR],
+[
+  AC_LIBSOURCES([memxor.h, memxor.c])
+  AC_LIBOBJ([memxor])
+])
diff --git a/gl/m4/restrict.m4 b/gl/m4/restrict.m4
new file mode 100644 (file)
index 0000000..1f3bbb9
--- /dev/null
@@ -0,0 +1,38 @@
+#serial 1003
+dnl Copyright (C) 2003 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.
+
+# This macro can be removed once we can rely on Autoconf 2.57a or later,
+# since we can then use its AC_C_RESTRICT.
+
+# gl_C_RESTRICT
+# --------------
+# Determine whether the C/C++ compiler supports the "restrict" keyword
+# introduced in ANSI C99, or an equivalent.  Do nothing if the compiler
+# accepts it.  Otherwise, if the compiler supports an equivalent,
+# define "restrict" to be that.  Here are some variants:
+# - GCC supports both __restrict and __restrict__
+# - older DEC Alpha C compilers support only __restrict
+# - _Restrict is the only spelling accepted by Sun WorkShop 6 update 2 C
+# Otherwise, define "restrict" to be empty.
+AC_DEFUN([gl_C_RESTRICT],
+[AC_CACHE_CHECK([for C/C++ restrict keyword], gl_cv_c_restrict,
+  [gl_cv_c_restrict=no
+   # Try the official restrict keyword, then gcc's __restrict, and
+   # the less common variants.
+   for ac_kw in restrict __restrict __restrict__ _Restrict; do
+     AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+      [float * $ac_kw x;])],
+      [gl_cv_c_restrict=$ac_kw; break])
+   done
+  ])
+ case $gl_cv_c_restrict in
+   restrict) ;;
+   no) AC_DEFINE(restrict,,
+       [Define to equivalent of C99 restrict keyword, or to nothing if this
+       is not supported.  Do not define if restrict is supported directly.]) ;;
+   *)  AC_DEFINE_UNQUOTED(restrict, $gl_cv_c_restrict) ;;
+ esac
+])
diff --git a/gl/m4/sha1.m4 b/gl/m4/sha1.m4
new file mode 100644 (file)
index 0000000..7b6c21c
--- /dev/null
@@ -0,0 +1,15 @@
+# sha1.m4 serial 6
+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_SHA1],
+[
+  AC_LIBSOURCES([sha1.c, sha1.h])
+  AC_LIBOBJ([sha1])
+
+  dnl Prerequisites of lib/sha1.c.
+  AC_REQUIRE([AC_C_BIGENDIAN])
+  :
+])
diff --git a/gl/m4/stdint.m4 b/gl/m4/stdint.m4
new file mode 100644 (file)
index 0000000..4875752
--- /dev/null
@@ -0,0 +1,58 @@
+# stdint.m4 serial 4
+dnl Copyright (C) 2001-2002, 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.
+
+dnl From Bruno Haible.
+dnl Test whether <stdint.h> is supported or must be substituted.
+
+AC_DEFUN([gl_STDINT_H],
+[dnl Check for <inttypes.h>.
+AC_REQUIRE([gt_HEADER_INTTYPES_H])
+dnl Check for <sys/inttypes.h>.
+AC_CHECK_HEADERS([sys/inttypes.h])
+
+AC_MSG_CHECKING([for stdint.h])
+AC_CACHE_VAL(gl_cv_header_stdint_h, [
+  AC_TRY_COMPILE([#include <stdint.h>], [],
+    gl_cv_header_stdint_h=yes, gl_cv_header_stdint_h=no)])
+AC_MSG_RESULT([$gl_cv_header_stdint_h])
+if test $gl_cv_header_stdint_h = yes; then
+  AC_DEFINE(HAVE_STDINT_H, 1,
+            [Define if you have a working <stdint.h> header file.])
+  STDINT_H=''
+else
+  STDINT_H='stdint.h'
+
+  dnl Is long == int64_t ?
+  AC_CACHE_CHECK([whether 'long' is 64 bit wide], gl_cv_long_bitsize_64, [
+    AC_TRY_COMPILE([
+#define POW63  ((((((long) 1 << 15) << 15) << 15) << 15) << 3)
+#define POW64  ((((((long) 1 << 15) << 15) << 15) << 15) << 4)
+typedef int array [2 * (POW63 != 0 && POW64 == 0) - 1];
+], , gl_cv_long_bitsize_64=yes, gl_cv_long_bitsize_64=no)])
+  if test $gl_cv_long_bitsize_64 = yes; then
+    HAVE_LONG_64BIT=1
+  else
+    HAVE_LONG_64BIT=0
+  fi
+  AC_SUBST(HAVE_LONG_64BIT)
+
+  dnl Is long long == int64_t ?
+  AC_CACHE_CHECK([whether 'long long' is 64 bit wide], gl_cv_longlong_bitsize_64, [
+    AC_TRY_COMPILE([
+#define POW63  ((((((long long) 1 << 15) << 15) << 15) << 15) << 3)
+#define POW64  ((((((long long) 1 << 15) << 15) << 15) << 15) << 4)
+typedef int array [2 * (POW63 != 0 && POW64 == 0) - 1];
+], , gl_cv_longlong_bitsize_64=yes, gl_cv_longlong_bitsize_64=no)])
+  if test $gl_cv_longlong_bitsize_64 = yes; then
+    HAVE_LONG_LONG_64BIT=1
+  else
+    HAVE_LONG_LONG_64BIT=0
+  fi
+  AC_SUBST(HAVE_LONG_LONG_64BIT)
+
+fi
+AC_SUBST(STDINT_H)
+])
diff --git a/gl/memxor.c b/gl/memxor.c
new file mode 100644 (file)
index 0000000..a046844
--- /dev/null
@@ -0,0 +1,37 @@
+/* memxor.c -- perform binary exclusive OR operation of two memory blocks.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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.  The interface was inspired by memxor
+   in Niels Möller's Nettle. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "memxor.h"
+
+void *
+memxor (void *restrict dest, const void *restrict src, size_t n)
+{
+  char const *s = src;
+  char *d = dest;
+
+  for (; n > 0; n--)
+    *d++ ^= *s++;
+
+  return dest;
+}
diff --git a/gl/memxor.h b/gl/memxor.h
new file mode 100644 (file)
index 0000000..4f85f2d
--- /dev/null
@@ -0,0 +1,31 @@
+/* memxor.h -- perform binary exclusive OR operation on memory blocks.
+   Copyright (C) 2005 Free Software Foundation, Inc.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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.  The interface was inspired by memxor
+   in Niels Möller's Nettle. */
+
+#ifndef MEMXOR_H
+# define MEMXOR_H
+
+#include <stddef.h>
+
+/* Compute binary exclusive OR of memory areas DEST and SRC, putting
+   the result in DEST, of length N bytes.  Returns a pointer to
+   DEST. */
+void *memxor (void *restrict dest, const void *restrict src, size_t n);
+
+#endif /* MEMXOR_H */
diff --git a/gl/sha1.c b/gl/sha1.c
new file mode 100644 (file)
index 0000000..7339540
--- /dev/null
+++ b/gl/sha1.c
@@ -0,0 +1,423 @@
+/* sha1.c - Functions to compute SHA1 message digest of files or
+   memory blocks according to the NIST specification FIPS-180-1.
+
+   Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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 Scott G. Miller
+   Credits:
+      Robert Klep <robert@ilse.nl>  -- Expansion function fix
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "sha1.h"
+
+#include <stddef.h>
+#include <string.h>
+
+#if USE_UNLOCKED_IO
+# include "unlocked-io.h"
+#endif
+
+/* SWAP does an endian swap on architectures that are little-endian,
+   as SHA1 needs some data in a big-endian form.  */
+
+#ifdef WORDS_BIGENDIAN
+# define SWAP(n) (n)
+#else
+# define SWAP(n) \
+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
+#endif
+
+#define BLOCKSIZE 4096
+#if BLOCKSIZE % 64 != 0
+# error "invalid BLOCKSIZE"
+#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, ...  */ };
+
+
+/*
+  Takes a pointer to a 160 bit block of data (five 32 bit ints) and
+  intializes it to the start constants of the SHA1 algorithm.  This
+  must be called before using hash in the call to sha1_hash.
+*/
+void
+sha1_init_ctx (struct sha1_ctx *ctx)
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+  ctx->E = 0xc3d2e1f0;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Put result from CTX in first 20 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 *
+sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
+{
+  ((uint32_t *) resbuf)[0] = SWAP (ctx->A);
+  ((uint32_t *) resbuf)[1] = SWAP (ctx->B);
+  ((uint32_t *) resbuf)[2] = SWAP (ctx->C);
+  ((uint32_t *) resbuf)[3] = SWAP (ctx->D);
+  ((uint32_t *) resbuf)[4] = SWAP (ctx->E);
+
+  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 *
+sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  uint32_t 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.  */
+  *(uint32_t *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
+  *(uint32_t *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
+                                                   (ctx->total[0] >> 29));
+
+  /* Process last bytes.  */
+  sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
+
+  return sha1_read_ctx (ctx, resbuf);
+}
+
+/* Compute SHA1 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int
+sha1_stream (FILE *stream, void *resblock)
+{
+  struct sha1_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  sha1_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
+       */
+      sha1_process_block (buffer, BLOCKSIZE, &ctx);
+    }
+
+ process_partial_block:;
+
+  /* Process any remaining bytes.  */
+  if (sum > 0)
+    sha1_process_bytes (buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  sha1_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 *
+sha1_buffer (const char *buffer, size_t len, void *resblock)
+{
+  struct sha1_ctx ctx;
+
+  /* Initialize the computation context.  */
+  sha1_init_ctx (&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  sha1_process_bytes (buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return sha1_finish_ctx (&ctx, resblock);
+}
+
+void
+sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
+{
+  /* 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)
+       {
+         sha1_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;
+    }
+
+  /* Process available complete blocks.  */
+  if (len >= 64)
+    {
+#if !_STRING_ARCH_unaligned
+# define alignof(type) offsetof (struct { char c; type x; }, x)
+# define UNALIGNED_P(p) (((size_t) p) % alignof (uint32_t) != 0)
+      if (UNALIGNED_P (buffer))
+       while (len > 64)
+         {
+           sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
+           buffer = (const char *) buffer + 64;
+           len -= 64;
+         }
+      else
+#endif
+       {
+         sha1_process_block (buffer, len & ~63, ctx);
+         buffer = (const char *) buffer + (len & ~63);
+         len &= 63;
+       }
+    }
+
+  /* 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)
+       {
+         sha1_process_block (ctx->buffer, 64, ctx);
+         left_over -= 64;
+         memcpy (ctx->buffer, &ctx->buffer[64], left_over);
+       }
+      ctx->buflen = left_over;
+    }
+}
+
+/* --- Code below is the primary difference between md5.c and sha1.c --- */
+
+/* SHA1 round constants */
+#define K1 0x5a827999L
+#define K2 0x6ed9eba1L
+#define K3 0x8f1bbcdcL
+#define K4 0xca62c1d6L
+
+/* Round functions.  Note that F2 is the same as F4.  */
+#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
+#define F2(B,C,D) (B ^ C ^ D)
+#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
+#define F4(B,C,D) (B ^ C ^ D)
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.
+   Most of this code comes from GnuPG's cipher/sha1.c.  */
+
+void
+sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
+{
+  const uint32_t *words = buffer;
+  size_t nwords = len / sizeof (uint32_t);
+  const uint32_t *endp = words + nwords;
+  uint32_t x[16];
+  uint32_t a = ctx->A;
+  uint32_t b = ctx->B;
+  uint32_t c = ctx->C;
+  uint32_t d = ctx->D;
+  uint32_t e = ctx->E;
+
+  /* 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];
+
+#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+#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)
+
+  while (words < endp)
+    {
+      uint32_t tm;
+      int t;
+      for (t = 0; t < 16; t++)
+       {
+         x[t] = SWAP (*words);
+         words++;
+       }
+
+      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) );
+
+      a = ctx->A += a;
+      b = ctx->B += b;
+      c = ctx->C += c;
+      d = ctx->D += d;
+      e = ctx->E += e;
+    }
+}
diff --git a/gl/sha1.h b/gl/sha1.h
new file mode 100644 (file)
index 0000000..fc6982d
--- /dev/null
+++ b/gl/sha1.h
@@ -0,0 +1,87 @@
+/* Declarations of functions and data types used for SHA1 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 Lesser General Public License as published by the
+   Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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 SHA1_H
+# define SHA1_H 1
+
+# include <stdio.h>
+# include <stdint.h>
+
+/* Structure to save state of computation between the single steps.  */
+struct sha1_ctx
+{
+  uint32_t A;
+  uint32_t B;
+  uint32_t C;
+  uint32_t D;
+  uint32_t E;
+
+  uint32_t total[2];
+  uint32_t buflen;
+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (uint32_t))));
+};
+
+
+/* Initialize structure containing state of computation. */
+extern void sha1_init_ctx (struct sha1_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 sha1_process_block (const void *buffer, size_t len,
+                               struct sha1_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 sha1_process_bytes (const void *buffer, size_t len,
+                               struct sha1_ctx *ctx);
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 20 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 *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
+
+
+/* Put result from CTX in first 20 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 *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
+
+
+/* Compute SHA1 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 20 bytes
+   beginning at RESBLOCK.  */
+extern int sha1_stream (FILE *stream, void *resblock);
+
+/* Compute SHA1 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 *sha1_buffer (const char *buffer, size_t len, void *resblock);
+
+#endif
diff --git a/gl/stdint_.h b/gl/stdint_.h
new file mode 100644 (file)
index 0000000..4695b27
--- /dev/null
@@ -0,0 +1,283 @@
+/* Copyright (C) 2001-2002, 2004-2005 Free Software Foundation, Inc.
+   Written by Bruno Haible, Sam Steingold, Peter Burwood.
+   This file is part of gnulib.
+
+   This program 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, 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 Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser 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 _STDINT_H
+#define _STDINT_H
+
+/*
+ * ISO C 99 <stdint.h> for platforms that lack it.
+ * <http://www.opengroup.org/onlinepubs/007904975/basedefs/stdint.h.html>
+ */
+
+/* Get wchar_t, WCHAR_MIN, WCHAR_MAX.  */
+#include <stddef.h>
+/* Get CHAR_BIT, LONG_MIN, LONG_MAX, ULONG_MAX.  */
+#include <limits.h>
+
+/* Get those types that are already defined in other system include files.  */
+#if defined(__FreeBSD__)
+# include <sys/inttypes.h>
+#endif
+#if defined(__sun) && HAVE_SYS_INTTYPES_H
+# include <sys/inttypes.h>
+  /* Solaris 7 <sys/inttypes.h> has the types except the *_fast*_t types, and
+     the macros except for *_FAST*_*, INTPTR_MIN, PTRDIFF_MIN, PTRDIFF_MAX.
+     But note that <sys/int_types.h> contains only the type definitions!  */
+# define _STDINT_H_HAVE_SYSTEM_INTTYPES
+#endif
+#if (defined(__hpux) || defined(_AIX)) && HAVE_INTTYPES_H
+# include <inttypes.h>
+  /* HP-UX 10 <inttypes.h> has nearly everything, except UINT_LEAST8_MAX,
+     UINT_FAST8_MAX, PTRDIFF_MIN, PTRDIFF_MAX.  */
+  /* AIX 4 <inttypes.h> has nearly everything, except INTPTR_MIN, INTPTR_MAX,
+     UINTPTR_MAX, PTRDIFF_MIN, PTRDIFF_MAX.  */
+# define _STDINT_H_HAVE_SYSTEM_INTTYPES
+#endif
+#if !(defined(UNIX_CYGWIN32) && defined(__BIT_TYPES_DEFINED__))
+# define _STDINT_H_NEED_SIGNED_INT_TYPES
+#endif
+
+#if !defined(_STDINT_H_HAVE_SYSTEM_INTTYPES)
+
+/* 7.18.1.1. Exact-width integer types */
+
+#if !defined(__FreeBSD__)
+
+#ifdef _STDINT_H_NEED_SIGNED_INT_TYPES
+typedef signed char    int8_t;
+#endif
+typedef unsigned char  uint8_t;
+
+#ifdef _STDINT_H_NEED_SIGNED_INT_TYPES
+typedef short          int16_t;
+#endif
+typedef unsigned short uint16_t;
+
+#ifdef _STDINT_H_NEED_SIGNED_INT_TYPES
+typedef int            int32_t;
+#endif
+typedef unsigned int   uint32_t;
+
+#if @HAVE_LONG_64BIT@
+#ifdef _STDINT_H_NEED_SIGNED_INT_TYPES
+typedef long           int64_t;
+#endif
+typedef unsigned long  uint64_t;
+#define _STDINT_H_HAVE_INT64
+#elif @HAVE_LONG_LONG_64BIT@
+#ifdef _STDINT_H_NEED_SIGNED_INT_TYPES
+typedef long long          int64_t;
+#endif
+typedef unsigned long long uint64_t;
+#define _STDINT_H_HAVE_INT64
+#elif defined(_MSC_VER)
+typedef __int64          int64_t;
+typedef unsigned __int64 uint64_t;
+#define _STDINT_H_HAVE_INT64
+#endif
+
+#endif /* !FreeBSD */
+
+/* 7.18.1.2. Minimum-width integer types */
+
+typedef int8_t   int_least8_t;
+typedef uint8_t  uint_least8_t;
+typedef int16_t  int_least16_t;
+typedef uint16_t uint_least16_t;
+typedef int32_t  int_least32_t;
+typedef uint32_t uint_least32_t;
+#ifdef _STDINT_H_HAVE_INT64
+typedef int64_t  int_least64_t;
+typedef uint64_t uint_least64_t;
+#endif
+
+/* 7.18.1.3. Fastest minimum-width integer types */
+
+typedef int32_t  int_fast8_t;
+typedef uint32_t uint_fast8_t;
+typedef int32_t  int_fast16_t;
+typedef uint32_t uint_fast16_t;
+typedef int32_t  int_fast32_t;
+typedef uint32_t uint_fast32_t;
+#ifdef _STDINT_H_HAVE_INT64
+typedef int64_t  int_fast64_t;
+typedef uint64_t uint_fast64_t;
+#endif
+
+/* 7.18.1.4. Integer types capable of holding object pointers */
+
+#if !defined(__FreeBSD__)
+
+/* On some platforms (like IRIX6 MIPS with -n32) sizeof(void*) < sizeof(long),
+   but this doesn't matter here.  */
+typedef long          intptr_t;
+typedef unsigned long uintptr_t;
+
+#endif /* !FreeBSD */
+
+/* 7.18.1.5. Greatest-width integer types */
+
+#ifdef _STDINT_H_HAVE_INT64
+typedef int64_t  intmax_t;
+typedef uint64_t uintmax_t;
+#else
+typedef int32_t  intmax_t;
+typedef uint32_t uintmax_t;
+#endif
+
+/* 7.18.2. Limits of specified-width integer types */
+
+#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS)
+
+/* 7.18.2.1. Limits of exact-width integer types */
+
+#define INT8_MIN  -128
+#define INT8_MAX   127
+#define UINT8_MAX  255U
+#define INT16_MIN  -32768
+#define INT16_MAX   32767
+#define UINT16_MAX  65535U
+#define INT32_MIN   (~INT32_MAX)
+#define INT32_MAX   2147483647
+#define UINT32_MAX  4294967295U
+#ifdef _STDINT_H_HAVE_INT64
+#define INT64_MIN   (~INT64_MAX)
+#if @HAVE_LONG_64BIT@
+#define INT64_MAX   9223372036854775807L
+#define UINT64_MAX 18446744073709551615UL
+#elif @HAVE_LONG_LONG_64BIT@
+#define INT64_MAX   9223372036854775807LL
+#define UINT64_MAX 18446744073709551615ULL
+#elif defined(_MSC_VER)
+#define INT64_MAX   9223372036854775807i64
+#define UINT64_MAX 18446744073709551615ui64
+#endif
+#endif
+
+/* 7.18.2.2. Limits of minimum-width integer types */
+
+#define INT_LEAST8_MIN INT8_MIN
+#define INT_LEAST8_MAX INT8_MAX
+#define UINT_LEAST8_MAX UINT8_MAX
+#define INT_LEAST16_MIN INT16_MIN
+#define INT_LEAST16_MAX INT16_MAX
+#define UINT_LEAST16_MAX UINT16_MAX
+#define INT_LEAST32_MIN INT32_MIN
+#define INT_LEAST32_MAX INT32_MAX
+#define UINT_LEAST32_MAX UINT32_MAX
+#ifdef _STDINT_H_HAVE_INT64
+#define INT_LEAST64_MIN INT64_MIN
+#define INT_LEAST64_MAX INT64_MAX
+#define UINT_LEAST64_MAX UINT64_MAX
+#endif
+
+/* 7.18.2.3. Limits of fastest minimum-width integer types */
+
+#define INT_FAST8_MIN INT32_MIN
+#define INT_FAST8_MAX INT32_MAX
+#define UINT_FAST8_MAX UINT32_MAX
+#define INT_FAST16_MIN INT32_MIN
+#define INT_FAST16_MAX INT32_MAX
+#define UINT_FAST16_MAX UINT32_MAX
+#define INT_FAST32_MIN INT32_MIN
+#define INT_FAST32_MAX INT32_MAX
+#define UINT_FAST32_MAX UINT32_MAX
+#ifdef _STDINT_H_HAVE_INT64
+#define INT_FAST64_MIN INT64_MIN
+#define INT_FAST64_MAX INT64_MAX
+#define UINT_FAST64_MAX UINT64_MAX
+#endif
+
+/* 7.18.2.4. Limits of integer types capable of holding object pointers */
+
+#define INTPTR_MIN LONG_MIN
+#define INTPTR_MAX LONG_MAX
+#define UINTPTR_MAX ULONG_MAX
+
+/* 7.18.2.5. Limits of greatest-width integer types */
+
+#ifdef _STDINT_H_HAVE_INT64
+#define INTMAX_MIN INT64_MIN
+#define INTMAX_MAX INT64_MAX
+#define UINTMAX_MAX UINT64_MAX
+#else
+#define INTMAX_MIN INT32_MIN
+#define INTMAX_MAX INT32_MAX
+#define UINTMAX_MAX UINT32_MAX
+#endif
+
+/* 7.18.3. Limits of other integer types */
+
+#define PTRDIFF_MIN (~(ptrdiff_t)0 << (sizeof(ptrdiff_t)*CHAR_BIT-1))
+#define PTRDIFF_MAX (~PTRDIFF_MIN)
+
+/* This may be wrong...  */
+#define SIG_ATOMIC_MIN 0
+#define SIG_ATOMIC_MAX 127
+
+#define SIZE_MAX (~(size_t)0)
+
+/* wchar_t limits already defined in <stddef.h>.  */
+/* wint_t limits already defined in <wchar.h>.  */
+
+#endif
+
+/* 7.18.4. Macros for integer constants */
+
+#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS)
+
+/* 7.18.4.1. Macros for minimum-width integer constants */
+
+#define INT8_C(x) x
+#define UINT8_C(x) x##U
+#define INT16_C(x) x
+#define UINT16_C(x) x##U
+#define INT32_C(x) x
+#define UINT32_C(x) x##U
+#if @HAVE_LONG_64BIT@
+#define INT64_C(x) x##L
+#define UINT64_C(x) x##UL
+#elif @HAVE_LONG_LONG_64BIT@
+#define INT64_C(x) x##LL
+#define UINT64_C(x) x##ULL
+#elif defined(_MSC_VER)
+#define INT64_C(x) x##i64
+#define UINT64_C(x) x##ui64
+#endif
+
+/* 7.18.4.2. Macros for greatest-width integer constants */
+
+#if @HAVE_LONG_64BIT@
+#define INTMAX_C(x) x##L
+#define UINTMAX_C(x) x##UL
+#elif @HAVE_LONG_LONG_64BIT@
+#define INTMAX_C(x) x##LL
+#define UINTMAX_C(x) x##ULL
+#elif defined(_MSC_VER)
+#define INTMAX_C(x) x##i64
+#define UINTMAX_C(x) x##ui64
+#else
+#define INTMAX_C(x) x
+#define UINTMAX_C(x) x##U
+#endif
+
+#endif
+
+#endif  /* !_STDINT_H_HAVE_SYSTEM_INTTYPES */
+
+#endif /* _STDINT_H */