diff options
-rw-r--r-- | gl/Makefile.am | 22 | ||||
-rw-r--r-- | gl/gc-gnulib.c | 207 | ||||
-rw-r--r-- | gl/gc-libgcrypt.c | 271 | ||||
-rw-r--r-- | gl/gc-pbkdf2-sha1.c | 187 | ||||
-rw-r--r-- | gl/gc.h | 241 | ||||
-rw-r--r-- | gl/hmac-sha1.c | 76 | ||||
-rw-r--r-- | gl/hmac.h | 41 | ||||
-rw-r--r-- | gl/m4/gc-hmac-sha1.m4 | 17 | ||||
-rw-r--r-- | gl/m4/gc-pbkdf2-sha1.m4 | 11 | ||||
-rw-r--r-- | gl/m4/gc.m4 | 99 | ||||
-rw-r--r-- | gl/m4/gnulib-cache.m4 | 4 | ||||
-rw-r--r-- | gl/m4/gnulib-comp.m4 | 25 | ||||
-rw-r--r-- | gl/m4/hmac-sha1.m4 | 11 | ||||
-rw-r--r-- | gl/m4/inttypes.m4 | 25 | ||||
-rw-r--r-- | gl/m4/memxor.m4 | 11 | ||||
-rw-r--r-- | gl/m4/restrict.m4 | 38 | ||||
-rw-r--r-- | gl/m4/sha1.m4 | 15 | ||||
-rw-r--r-- | gl/m4/stdint.m4 | 58 | ||||
-rw-r--r-- | gl/memxor.c | 37 | ||||
-rw-r--r-- | gl/memxor.h | 31 | ||||
-rw-r--r-- | gl/sha1.c | 423 | ||||
-rw-r--r-- | gl/sha1.h | 87 | ||||
-rw-r--r-- | gl/stdint_.h | 283 |
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 */ |