summaryrefslogtreecommitdiff
path: root/gl
diff options
context:
space:
mode:
authorSimon Josefsson <simon@josefsson.org>2005-10-12 13:36:53 +0000
committerSimon Josefsson <simon@josefsson.org>2005-10-12 13:36:53 +0000
commitebc7c5efd9bfc0993e365504afa4c07b79452244 (patch)
tree9dc37fdd5037a7c1c10c7086582fc32daa5128dd /gl
parent43a7d7b83dee950580e7b9f5edd044236645885c (diff)
downloadgnutls-ebc7c5efd9bfc0993e365504afa4c07b79452244.tar.gz
Update.
Diffstat (limited to 'gl')
-rw-r--r--gl/Makefile.am22
-rw-r--r--gl/gc-gnulib.c207
-rw-r--r--gl/gc-libgcrypt.c271
-rw-r--r--gl/gc-pbkdf2-sha1.c187
-rw-r--r--gl/gc.h241
-rw-r--r--gl/hmac-sha1.c76
-rw-r--r--gl/hmac.h41
-rw-r--r--gl/m4/gc-hmac-sha1.m417
-rw-r--r--gl/m4/gc-pbkdf2-sha1.m411
-rw-r--r--gl/m4/gc.m499
-rw-r--r--gl/m4/gnulib-cache.m44
-rw-r--r--gl/m4/gnulib-comp.m425
-rw-r--r--gl/m4/hmac-sha1.m411
-rw-r--r--gl/m4/inttypes.m425
-rw-r--r--gl/m4/memxor.m411
-rw-r--r--gl/m4/restrict.m438
-rw-r--r--gl/m4/sha1.m415
-rw-r--r--gl/m4/stdint.m458
-rw-r--r--gl/memxor.c37
-rw-r--r--gl/memxor.h31
-rw-r--r--gl/sha1.c423
-rw-r--r--gl/sha1.h87
-rw-r--r--gl/stdint_.h283
23 files changed, 2217 insertions, 3 deletions
diff --git a/gl/Makefile.am b/gl/Makefile.am
index 1e164be1bc..6220ae0ee0 100644
--- a/gl/Makefile.am
+++ b/gl/Makefile.am
@@ -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
index 0000000000..9d6cfebd6f
--- /dev/null
+++ b/gl/gc-gnulib.c
@@ -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
index 0000000000..6b985c9e1a
--- /dev/null
+++ b/gl/gc-libgcrypt.c
@@ -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
index 0000000000..0317b3aca0
--- /dev/null
+++ b/gl/gc-pbkdf2-sha1.c
@@ -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
index 0000000000..3a000ba0ca
--- /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
index 0000000000..4ebcb5923f
--- /dev/null
+++ b/gl/hmac-sha1.c
@@ -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
index 0000000000..5965b60326
--- /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
index 0000000000..b6a3fa47d4
--- /dev/null
+++ b/gl/m4/gc-hmac-sha1.m4
@@ -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
index 0000000000..674f739677
--- /dev/null
+++ b/gl/m4/gc-pbkdf2-sha1.m4
@@ -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
index 0000000000..bf46b92e64
--- /dev/null
+++ b/gl/m4/gc.m4
@@ -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], [:])
diff --git a/gl/m4/gnulib-cache.m4 b/gl/m4/gnulib-cache.m4
index 3c9d09e5ef..1801f66b4b 100644
--- a/gl/m4/gnulib-cache.m4
+++ b/gl/m4/gnulib-cache.m4
@@ -14,10 +14,10 @@
# 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])
diff --git a/gl/m4/gnulib-comp.m4 b/gl/m4/gnulib-comp.m4
index 74de8b6f09..dc37674189 100644
--- a/gl/m4/gnulib-comp.m4
+++ b/gl/m4/gnulib-comp.m4
@@ -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
index 0000000000..1e95822f4a
--- /dev/null
+++ b/gl/m4/hmac-sha1.m4
@@ -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
index 0000000000..779bcea059
--- /dev/null
+++ b/gl/m4/inttypes.m4
@@ -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
index 0000000000..96764cfbf6
--- /dev/null
+++ b/gl/m4/memxor.m4
@@ -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
index 0000000000..1f3bbb92c4
--- /dev/null
+++ b/gl/m4/restrict.m4
@@ -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
index 0000000000..7b6c21cb83
--- /dev/null
+++ b/gl/m4/sha1.m4
@@ -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
index 0000000000..4875752de8
--- /dev/null
+++ b/gl/m4/stdint.m4
@@ -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
index 0000000000..a046844604
--- /dev/null
+++ b/gl/memxor.c
@@ -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
index 0000000000..4f85f2d7e9
--- /dev/null
+++ b/gl/memxor.h
@@ -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
index 0000000000..7339540e27
--- /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
index 0000000000..fc6982dfe3
--- /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
index 0000000000..4695b27830
--- /dev/null
+++ b/gl/stdint_.h
@@ -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 */