Use libcrypto's checksum implementations if available, for speed.
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 8 Dec 2013 08:05:36 +0000 (00:05 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 8 Dec 2013 08:05:36 +0000 (00:05 -0800)
On commonly used platform libcrypto uses architecture-specific
assembly code, which is significantly faster than the C code we
were using.  See Pádraig Brady's note in
<http://lists.gnu.org/archive/html/bug-gnulib/2013-12/msg00000.html>.
Merge from gnulib, incorporating:
2013-12-07 md5, sha1, sha256, sha512: add gl_SET_CRYPTO_CHECK_DEFAULT
2013-12-07 md5, sha1, sha256, sha512: add 'auto', and set-default method
2013-12-04 include_next: minimize code duplication
2013-12-03 md5, sha1, sha256, sha512: support mandating use of openssl
2013-12-02 md5, sha1, sha256, sha512: use openssl routines if available
* configure.ac (--without-all): Set with_openssl_default too.
Use gl_SET_CRYPTO_CHECK_DEFAULT to default to 'auto'.
(HAVE_LIB_CRYPTO): New var.
Say whether Emacs is configured to use a crypto library.
* lib/gl_openssl.h, m4/absolute-header.m4, m4/gl-openssl.m4:
New files, copied from gnulib.
* lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
* lib/md5.c, lib/md5.h, lib/sha1.c, lib/sha1.h:
* lib/sha256.c, lib/sha256.h, lib/sha512.c, lib/sha512.h:
* m4/include_next.m4, m4/md5.m4, m4/sha1.m4, m4/sha256.m4, m4/sha512.m4:
Update from gnulib.
* src/Makefile.in (LIB_CRYPTO): New macro.
(LIBES): Use it.

22 files changed:
ChangeLog
configure.ac
lib/gl_openssl.h [new file with mode: 0644]
lib/gnulib.mk
lib/md5.c
lib/md5.h
lib/sha1.c
lib/sha1.h
lib/sha256.c
lib/sha256.h
lib/sha512.c
lib/sha512.h
m4/absolute-header.m4 [new file with mode: 0644]
m4/gl-openssl.m4 [new file with mode: 0644]
m4/gnulib-comp.m4
m4/include_next.m4
m4/md5.m4
m4/sha1.m4
m4/sha256.m4
m4/sha512.m4
src/ChangeLog
src/Makefile.in

index 6183719..724218c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2013-12-08  Paul Eggert  <eggert@cs.ucla.edu>
+
+       Use libcrypto's checksum implementations if available, for speed.
+       On commonly used platform libcrypto uses architecture-specific
+       assembly code, which is significantly faster than the C code we
+       were using.  See Pádraig Brady's note in
+       <http://lists.gnu.org/archive/html/bug-gnulib/2013-12/msg00000.html>.
+       Merge from gnulib, incorporating:
+       2013-12-07 md5, sha1, sha256, sha512: add gl_SET_CRYPTO_CHECK_DEFAULT
+       2013-12-07 md5, sha1, sha256, sha512: add 'auto', and set-default method
+       2013-12-04 include_next: minimize code duplication
+       2013-12-03 md5, sha1, sha256, sha512: support mandating use of openssl
+       2013-12-02 md5, sha1, sha256, sha512: use openssl routines if available
+       * configure.ac (--without-all): Set with_openssl_default too.
+       Use gl_SET_CRYPTO_CHECK_DEFAULT to default to 'auto'.
+       (HAVE_LIB_CRYPTO): New var.
+       Say whether Emacs is configured to use a crypto library.
+       * lib/gl_openssl.h, m4/absolute-header.m4, m4/gl-openssl.m4:
+       New files, copied from gnulib.
+       * lib/gnulib.mk, m4/gnulib-comp.m4: Regenerate.
+       * lib/md5.c, lib/md5.h, lib/sha1.c, lib/sha1.h:
+       * lib/sha256.c, lib/sha256.h, lib/sha512.c, lib/sha512.h:
+       * m4/include_next.m4, m4/md5.m4, m4/sha1.m4, m4/sha256.m4, m4/sha512.m4:
+       Update from gnulib.
+
 2013-12-01  Dmitry Gutov  <dgutov@yandex.ru>
 
        * .dir-locals.el (log-edit-move): Add the "Author: " header.
index 46ddb43..264c339 100644 (file)
@@ -94,8 +94,9 @@ AC_ARG_WITH(all,
 [AS_HELP_STRING([--without-all],
                [omit almost all features and build
                small executable with minimal dependencies])],
-  with_features=$withval,
-  with_features=yes)
+  [with_features=$withval
+   with_openssl_default=$withval],
+  [with_features=yes])
 
 dnl OPTION_DEFAULT_OFF(NAME, HELP-STRING)
 dnl Create a new --with option that defaults to being disabled.
@@ -4691,6 +4692,7 @@ CFLAGS=$pre_PKG_CONFIG_CFLAGS
 LIBS="$LIB_PTHREAD $pre_PKG_CONFIG_LIBS"
 gl_ASSERT_NO_GNULIB_POSIXCHECK
 gl_ASSERT_NO_GNULIB_TESTS
+gl_SET_CRYPTO_CHECK_DEFAULT([auto])
 gl_INIT
 CFLAGS=$SAVE_CFLAGS
 LIBS=$SAVE_LIBS
@@ -4842,6 +4844,12 @@ else
   acl_summary=no
 fi
 
+if test -n "$LIB_CRYPTO"; then
+  HAVE_LIB_CRYPTO=yes
+else
+  HAVE_LIB_CRYPTO=no
+fi
+
 echo "
 Configured for \`${canonical}'.
 
@@ -4881,6 +4889,7 @@ echo "  Does Emacs use -lgconf?                                 ${HAVE_GCONF}"
 echo "  Does Emacs use GSettings?                               ${HAVE_GSETTINGS}"
 echo "  Does Emacs use a file notification library?             ${NOTIFY_SUMMARY}"
 echo "  Does Emacs use access control lists?                    ${acl_summary}"
+echo "  Does Emacs use a crypto library?                        ${HAVE_LIB_CRYPTO} $LIB_CRYPTO"
 echo "  Does Emacs use -lselinux?                               ${HAVE_LIBSELINUX}"
 echo "  Does Emacs use -lgnutls?                                ${HAVE_GNUTLS}"
 echo "  Does Emacs use -lxml2?                                  ${HAVE_LIBXML2}"
diff --git a/lib/gl_openssl.h b/lib/gl_openssl.h
new file mode 100644 (file)
index 0000000..1fb6106
--- /dev/null
@@ -0,0 +1,116 @@
+/* gl_openssl.h -- wrap openssl crypto hash routines in gnulib interface
+
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Pádraig Brady */
+
+#ifndef GL_OPENSSL_NAME
+# error "Please define GL_OPENSSL_NAME to 1,5,256 etc."
+#endif
+
+#ifndef _GL_INLINE_HEADER_BEGIN
+# error "Please include config.h first."
+#endif
+_GL_INLINE_HEADER_BEGIN
+#ifndef GL_OPENSSL_INLINE
+# define GL_OPENSSL_INLINE _GL_INLINE
+#endif
+
+/* Concatenate two preprocessor tokens.  */
+#define _GLCRYPTO_CONCAT_(prefix, suffix) prefix##suffix
+#define _GLCRYPTO_CONCAT(prefix, suffix) _GLCRYPTO_CONCAT_ (prefix, suffix)
+
+#if GL_OPENSSL_NAME == 5
+# define OPENSSL_ALG md5
+#else
+# define OPENSSL_ALG _GLCRYPTO_CONCAT (sha, GL_OPENSSL_NAME)
+#endif
+
+/* Context type mappings.  */
+#if BASE_OPENSSL_TYPE != GL_OPENSSL_NAME
+# undef BASE_OPENSSL_TYPE
+# if GL_OPENSSL_NAME == 224
+#  define BASE_OPENSSL_TYPE 256
+# elif GL_OPENSSL_NAME == 384
+#  define BASE_OPENSSL_TYPE 512
+# endif
+# define md5_CTX MD5_CTX
+# define sha1_CTX SHA_CTX
+# define sha224_CTX SHA256_CTX
+# define sha224_ctx sha256_ctx
+# define sha256_CTX SHA256_CTX
+# define sha384_CTX SHA512_CTX
+# define sha384_ctx sha512_ctx
+# define sha512_CTX SHA512_CTX
+# undef _gl_CTX
+# undef _gl_ctx
+# define _gl_CTX _GLCRYPTO_CONCAT (OPENSSL_ALG, _CTX) /* openssl type.  */
+# define _gl_ctx _GLCRYPTO_CONCAT (OPENSSL_ALG, _ctx) /* gnulib type.  */
+
+struct _gl_ctx { _gl_CTX CTX; };
+#endif
+
+/* Function name mappings.  */
+#define md5_prefix MD5
+#define sha1_prefix SHA1
+#define sha224_prefix SHA224
+#define sha256_prefix SHA256
+#define sha384_prefix SHA384
+#define sha512_prefix SHA512
+#define _GLCRYPTO_PREFIX _GLCRYPTO_CONCAT (OPENSSL_ALG, _prefix)
+#define OPENSSL_FN(suffix) _GLCRYPTO_CONCAT (_GLCRYPTO_PREFIX, suffix)
+#define GL_CRYPTO_FN(suffix) _GLCRYPTO_CONCAT (OPENSSL_ALG, suffix)
+
+GL_OPENSSL_INLINE void
+GL_CRYPTO_FN (_init_ctx) (struct _gl_ctx *ctx)
+{ (void) OPENSSL_FN (_Init) ((_gl_CTX *) ctx); }
+
+/* These were never exposed by gnulib.  */
+#if ! (GL_OPENSSL_NAME == 224 || GL_OPENSSL_NAME == 384)
+GL_OPENSSL_INLINE void
+GL_CRYPTO_FN (_process_bytes) (const void *buf, size_t len, struct _gl_ctx *ctx)
+{ OPENSSL_FN (_Update) ((_gl_CTX *) ctx, buf, len); }
+
+GL_OPENSSL_INLINE void
+GL_CRYPTO_FN (_process_block) (const void *buf, size_t len, struct _gl_ctx *ctx)
+{ GL_CRYPTO_FN (_process_bytes) (buf, len, ctx); }
+#endif
+
+GL_OPENSSL_INLINE void *
+GL_CRYPTO_FN (_finish_ctx) (struct _gl_ctx *ctx, void *res)
+{ OPENSSL_FN (_Final) (res, (_gl_CTX *) ctx); return res; }
+
+GL_OPENSSL_INLINE void *
+GL_CRYPTO_FN (_buffer) (const char *buf, size_t len, void *res)
+{ return OPENSSL_FN () ((const unsigned char *) buf, len, res); }
+
+GL_OPENSSL_INLINE void *
+GL_CRYPTO_FN (_read_ctx) (const struct _gl_ctx *ctx, void *res)
+{
+  /* Assume any unprocessed bytes in ctx are not to be ignored.  */
+  _gl_CTX tmp_ctx = *(_gl_CTX *) ctx;
+  OPENSSL_FN (_Final) (res, &tmp_ctx);
+  return res;
+}
+
+/* Undef so we can include multiple times.  */
+#undef GL_CRYPTO_FN
+#undef OPENSSL_FN
+#undef _GLCRYPTO_PREFIX
+#undef OPENSSL_ALG
+#undef GL_OPENSSL_NAME
+
+_GL_INLINE_HEADER_END
index 44cdc0c..9617452 100644 (file)
@@ -33,6 +33,15 @@ libgnu_a_LIBADD = $(gl_LIBOBJS)
 libgnu_a_DEPENDENCIES = $(gl_LIBOBJS)
 EXTRA_libgnu_a_SOURCES =
 
+## begin gnulib module absolute-header
+
+# Use this preprocessor expression to decide whether #include_next works.
+# Do not rely on a 'configure'-time test for this, since the expression
+# might appear in an installed header, which is used by some other compiler.
+HAVE_INCLUDE_NEXT = (__GNUC__ || 60000000 <= __DECC_VER)
+
+## end   gnulib module absolute-header
+
 ## begin gnulib module alloca-opt
 
 BUILT_SOURCES += $(ALLOCA_H)
@@ -152,7 +161,7 @@ EXTRA_DIST += count-trailing-zeros.h
 
 libgnu_a_SOURCES += md5.c
 
-EXTRA_DIST += md5.h
+EXTRA_DIST += gl_openssl.h md5.h
 
 ## end   gnulib module crypto/md5
 
@@ -160,7 +169,7 @@ EXTRA_DIST += md5.h
 
 libgnu_a_SOURCES += sha1.c
 
-EXTRA_DIST += sha1.h
+EXTRA_DIST += gl_openssl.h sha1.h
 
 ## end   gnulib module crypto/sha1
 
@@ -168,7 +177,7 @@ EXTRA_DIST += sha1.h
 
 libgnu_a_SOURCES += sha256.c
 
-EXTRA_DIST += sha256.h
+EXTRA_DIST += gl_openssl.h sha256.h
 
 ## end   gnulib module crypto/sha256
 
@@ -176,7 +185,7 @@ EXTRA_DIST += sha256.h
 
 libgnu_a_SOURCES += sha512.c
 
-EXTRA_DIST += sha512.h
+EXTRA_DIST += gl_openssl.h sha512.h
 
 ## end   gnulib module crypto/sha512
 
index f41b5be..ea2c1d5 100644 (file)
--- a/lib/md5.c
+++ b/lib/md5.c
@@ -21,6 +21,9 @@
 
 #include <config.h>
 
+#if HAVE_OPENSSL_MD5
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
 #include "md5.h"
 
 #include <stdalign.h>
@@ -61,6 +64,7 @@
 # error "invalid BLOCKSIZE"
 #endif
 
+#if ! HAVE_OPENSSL_MD5
 /* 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, ...  */ };
@@ -128,6 +132,7 @@ md5_finish_ctx (struct md5_ctx *ctx, void *resbuf)
 
   return md5_read_ctx (ctx, resbuf);
 }
+#endif
 
 /* Compute MD5 message digest for bytes read from STREAM.  The
    resulting message digest number will be written into the 16 bytes
@@ -202,6 +207,7 @@ process_partial_block:
   return 0;
 }
 
+#if ! HAVE_OPENSSL_MD5
 /* 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
@@ -459,3 +465,4 @@ md5_process_block (const void *buffer, size_t len, struct md5_ctx *ctx)
   ctx->C = C;
   ctx->D = D;
 }
+#endif
index 634a747..b09a68b 100644 (file)
--- a/lib/md5.h
+++ b/lib/md5.h
 #include <stdio.h>
 #include <stdint.h>
 
+# if HAVE_OPENSSL_MD5
+#  include <openssl/md5.h>
+# endif
+
 #define MD5_DIGEST_SIZE 16
 #define MD5_BLOCK_SIZE 64
 
 extern "C" {
 # endif
 
+# if HAVE_OPENSSL_MD5
+#  define GL_OPENSSL_NAME 5
+#  include "gl_openssl.h"
+# else
 /* Structure to save state of computation between the single steps.  */
 struct md5_ctx
 {
@@ -106,11 +114,6 @@ extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
 extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
 
 
-/* Compute MD5 message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 16 bytes
-   beginning at RESBLOCK.  */
-extern int __md5_stream (FILE *stream, void *resblock) __THROW;
-
 /* 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
@@ -118,6 +121,13 @@ extern int __md5_stream (FILE *stream, void *resblock) __THROW;
 extern void *__md5_buffer (const char *buffer, size_t len,
                            void *resblock) __THROW;
 
+# endif
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+extern int __md5_stream (FILE *stream, void *resblock) __THROW;
+
+
 # ifdef __cplusplus
 }
 # endif
index 778389a..b1a24f9 100644 (file)
@@ -23,6 +23,9 @@
 
 #include <config.h>
 
+#if HAVE_OPENSSL_SHA1
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
 #include "sha1.h"
 
 #include <stdalign.h>
@@ -46,6 +49,7 @@
 # error "invalid BLOCKSIZE"
 #endif
 
+#if ! HAVE_OPENSSL_SHA1
 /* 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, ...  */ };
@@ -116,6 +120,7 @@ sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
 
   return sha1_read_ctx (ctx, resbuf);
 }
+#endif
 
 /* Compute SHA1 message digest for bytes read from STREAM.  The
    resulting message digest number will be written into the 16 bytes
@@ -190,6 +195,7 @@ sha1_stream (FILE *stream, void *resblock)
   return 0;
 }
 
+#if ! HAVE_OPENSSL_SHA1
 /* 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
@@ -424,3 +430,4 @@ sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
       e = ctx->E += e;
     }
 }
+#endif
index ddd386f..0ec953e 100644 (file)
 # include <stdio.h>
 # include <stdint.h>
 
+# if HAVE_OPENSSL_SHA1
+#  include <openssl/sha.h>
+# endif
+
 # ifdef __cplusplus
 extern "C" {
 # endif
 
 #define SHA1_DIGEST_SIZE 20
 
+# if HAVE_OPENSSL_SHA1
+#  define GL_OPENSSL_NAME 1
+#  include "gl_openssl.h"
+# else
 /* Structure to save state of computation between the single steps.  */
 struct sha1_ctx
 {
@@ -42,7 +50,6 @@ struct sha1_ctx
   uint32_t buffer[32];
 };
 
-
 /* Initialize structure containing state of computation. */
 extern void sha1_init_ctx (struct sha1_ctx *ctx);
 
@@ -73,17 +80,19 @@ extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
 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
+/* 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);
+
+
 # ifdef __cplusplus
 }
 # endif
index 4b2cee3..9d6912c 100644 (file)
@@ -22,6 +22,9 @@
 
 #include <config.h>
 
+#if HAVE_OPENSSL_SHA256
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
 #include "sha256.h"
 
 #include <stdalign.h>
@@ -45,6 +48,7 @@
 # error "invalid BLOCKSIZE"
 #endif
 
+#if ! HAVE_OPENSSL_SHA256
 /* This array contains the bytes used to pad the buffer to the next
    64-byte boundary.  */
 static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
@@ -163,6 +167,7 @@ sha224_finish_ctx (struct sha256_ctx *ctx, void *resbuf)
   sha256_conclude_ctx (ctx);
   return sha224_read_ctx (ctx, resbuf);
 }
+#endif
 
 /* Compute SHA256 message digest for bytes read from STREAM.  The
    resulting message digest number will be written into the 32 bytes
@@ -308,6 +313,7 @@ sha224_stream (FILE *stream, void *resblock)
   return 0;
 }
 
+#if ! HAVE_OPENSSL_SHA256
 /* Compute SHA512 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
@@ -567,3 +573,4 @@ sha256_process_block (const void *buffer, size_t len, struct sha256_ctx *ctx)
       h = ctx->state[7] += h;
     }
 }
+#endif
index 7e62522..6ee326b 100644 (file)
 # include <stdio.h>
 # include <stdint.h>
 
+# if HAVE_OPENSSL_SHA256
+#  include <openssl/sha.h>
+# endif
+
 # ifdef __cplusplus
 extern "C" {
 # endif
 
+enum { SHA224_DIGEST_SIZE = 224 / 8 };
+enum { SHA256_DIGEST_SIZE = 256 / 8 };
+
+# if HAVE_OPENSSL_SHA256
+#  define GL_OPENSSL_NAME 224
+#  include "gl_openssl.h"
+#  define GL_OPENSSL_NAME 256
+#  include "gl_openssl.h"
+# else
 /* Structure to save state of computation between the single steps.  */
 struct sha256_ctx
 {
@@ -35,9 +48,6 @@ struct sha256_ctx
   uint32_t buffer[32];
 };
 
-enum { SHA224_DIGEST_SIZE = 224 / 8 };
-enum { SHA256_DIGEST_SIZE = 256 / 8 };
-
 /* Initialize structure containing state of computation. */
 extern void sha256_init_ctx (struct sha256_ctx *ctx);
 extern void sha224_init_ctx (struct sha256_ctx *ctx);
@@ -71,12 +81,6 @@ extern void *sha256_read_ctx (const struct sha256_ctx *ctx, void *resbuf);
 extern void *sha224_read_ctx (const struct sha256_ctx *ctx, void *resbuf);
 
 
-/* Compute SHA256 (SHA224) message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 32 (28) bytes
-   beginning at RESBLOCK.  */
-extern int sha256_stream (FILE *stream, void *resblock);
-extern int sha224_stream (FILE *stream, void *resblock);
-
 /* Compute SHA256 (SHA224) 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
@@ -84,6 +88,14 @@ extern int sha224_stream (FILE *stream, void *resblock);
 extern void *sha256_buffer (const char *buffer, size_t len, void *resblock);
 extern void *sha224_buffer (const char *buffer, size_t len, void *resblock);
 
+# endif
+/* Compute SHA256 (SHA224) message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 32 (28) bytes
+   beginning at RESBLOCK.  */
+extern int sha256_stream (FILE *stream, void *resblock);
+extern int sha224_stream (FILE *stream, void *resblock);
+
+
 # ifdef __cplusplus
 }
 # endif
index 79f1125..8429bb9 100644 (file)
@@ -22,6 +22,9 @@
 
 #include <config.h>
 
+#if HAVE_OPENSSL_SHA512
+# define GL_OPENSSL_INLINE _GL_EXTERN_INLINE
+#endif
 #include "sha512.h"
 
 #include <stdalign.h>
@@ -52,6 +55,7 @@
 # error "invalid BLOCKSIZE"
 #endif
 
+#if ! HAVE_OPENSSL_SHA512
 /* This array contains the bytes used to pad the buffer to the next
    128-byte boundary.  */
 static const unsigned char fillbuf[128] = { 0x80, 0 /* , 0, 0, ...  */ };
@@ -171,6 +175,7 @@ sha384_finish_ctx (struct sha512_ctx *ctx, void *resbuf)
   sha512_conclude_ctx (ctx);
   return sha384_read_ctx (ctx, resbuf);
 }
+#endif
 
 /* Compute SHA512 message digest for bytes read from STREAM.  The
    resulting message digest number will be written into the 64 bytes
@@ -316,6 +321,7 @@ sha384_stream (FILE *stream, void *resblock)
   return 0;
 }
 
+#if ! HAVE_OPENSSL_SHA512
 /* Compute SHA512 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
@@ -619,3 +625,4 @@ sha512_process_block (const void *buffer, size_t len, struct sha512_ctx *ctx)
       h = ctx->state[7] = u64plus (ctx->state[7], h);
     }
 }
+#endif
index 2e78a5f..1de93da 100644 (file)
 # define SHA512_H 1
 
 # include <stdio.h>
-
 # include "u64.h"
 
+# if HAVE_OPENSSL_SHA512
+#  include <openssl/sha.h>
+# endif
+
 # ifdef __cplusplus
 extern "C" {
 # endif
 
+enum { SHA384_DIGEST_SIZE = 384 / 8 };
+enum { SHA512_DIGEST_SIZE = 512 / 8 };
+
+# if HAVE_OPENSSL_SHA512
+#  define GL_OPENSSL_NAME 384
+#  include "gl_openssl.h"
+#  define GL_OPENSSL_NAME 512
+#  include "gl_openssl.h"
+# else
 /* Structure to save state of computation between the single steps.  */
 struct sha512_ctx
 {
@@ -36,9 +48,6 @@ struct sha512_ctx
   u64 buffer[32];
 };
 
-enum { SHA384_DIGEST_SIZE = 384 / 8 };
-enum { SHA512_DIGEST_SIZE = 512 / 8 };
-
 /* Initialize structure containing state of computation. */
 extern void sha512_init_ctx (struct sha512_ctx *ctx);
 extern void sha384_init_ctx (struct sha512_ctx *ctx);
@@ -75,12 +84,6 @@ extern void *sha512_read_ctx (const struct sha512_ctx *ctx, void *resbuf);
 extern void *sha384_read_ctx (const struct sha512_ctx *ctx, void *resbuf);
 
 
-/* Compute SHA512 (SHA384) message digest for bytes read from STREAM.  The
-   resulting message digest number will be written into the 64 (48) bytes
-   beginning at RESBLOCK.  */
-extern int sha512_stream (FILE *stream, void *resblock);
-extern int sha384_stream (FILE *stream, void *resblock);
-
 /* Compute SHA512 (SHA384) 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
@@ -88,6 +91,14 @@ extern int sha384_stream (FILE *stream, void *resblock);
 extern void *sha512_buffer (const char *buffer, size_t len, void *resblock);
 extern void *sha384_buffer (const char *buffer, size_t len, void *resblock);
 
+# endif
+/* Compute SHA512 (SHA384) message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 64 (48) bytes
+   beginning at RESBLOCK.  */
+extern int sha512_stream (FILE *stream, void *resblock);
+extern int sha384_stream (FILE *stream, void *resblock);
+
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/m4/absolute-header.m4 b/m4/absolute-header.m4
new file mode 100644 (file)
index 0000000..89ff5be
--- /dev/null
@@ -0,0 +1,102 @@
+# absolute-header.m4 serial 16
+dnl Copyright (C) 2006-2013 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 Derek Price.
+
+# gl_ABSOLUTE_HEADER(HEADER1 HEADER2 ...)
+# ---------------------------------------
+# Find the absolute name of a header file, testing first if the header exists.
+# If the header were sys/inttypes.h, this macro would define
+# ABSOLUTE_SYS_INTTYPES_H to the '""' quoted absolute name of sys/inttypes.h
+# in config.h
+# (e.g. '#define ABSOLUTE_SYS_INTTYPES_H "///usr/include/sys/inttypes.h"').
+# The three "///" are to pacify Sun C 5.8, which otherwise would say
+# "warning: #include of /usr/include/... may be non-portable".
+# Use '""', not '<>', so that the /// cannot be confused with a C99 comment.
+# Note: This macro assumes that the header file is not empty after
+# preprocessing, i.e. it does not only define preprocessor macros but also
+# provides some type/enum definitions or function/variable declarations.
+AC_DEFUN([gl_ABSOLUTE_HEADER],
+[AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_PREPROC_REQUIRE()dnl
+dnl FIXME: gl_absolute_header and ac_header_exists must be used unquoted
+dnl until we can assume autoconf 2.64 or newer.
+m4_foreach_w([gl_HEADER_NAME], [$1],
+  [AS_VAR_PUSHDEF([gl_absolute_header],
+                  [gl_cv_absolute_]m4_defn([gl_HEADER_NAME]))dnl
+  AC_CACHE_CHECK([absolute name of <]m4_defn([gl_HEADER_NAME])[>],
+    m4_defn([gl_absolute_header]),
+    [AS_VAR_PUSHDEF([ac_header_exists],
+                    [ac_cv_header_]m4_defn([gl_HEADER_NAME]))dnl
+    AC_CHECK_HEADERS_ONCE(m4_defn([gl_HEADER_NAME]))dnl
+    if test AS_VAR_GET(ac_header_exists) = yes; then
+      gl_ABSOLUTE_HEADER_ONE(m4_defn([gl_HEADER_NAME]))
+    fi
+    AS_VAR_POPDEF([ac_header_exists])dnl
+    ])dnl
+  AC_DEFINE_UNQUOTED(AS_TR_CPP([ABSOLUTE_]m4_defn([gl_HEADER_NAME])),
+                     ["AS_VAR_GET(gl_absolute_header)"],
+                     [Define this to an absolute name of <]m4_defn([gl_HEADER_NAME])[>.])
+  AS_VAR_POPDEF([gl_absolute_header])dnl
+])dnl
+])# gl_ABSOLUTE_HEADER
+
+# gl_ABSOLUTE_HEADER_ONE(HEADER)
+# ------------------------------
+# Like gl_ABSOLUTE_HEADER, except that:
+#   - it assumes that the header exists,
+#   - it uses the current CPPFLAGS,
+#   - it does not cache the result,
+#   - it is silent.
+AC_DEFUN([gl_ABSOLUTE_HEADER_ONE],
+[
+  AC_REQUIRE([AC_CANONICAL_HOST])
+  AC_LANG_CONFTEST([AC_LANG_SOURCE([[#include <]]m4_dquote([$1])[[>]])])
+  dnl AIX "xlc -E" and "cc -E" omit #line directives for header files
+  dnl that contain only a #include of other header files and no
+  dnl non-comment tokens of their own. This leads to a failure to
+  dnl detect the absolute name of <dirent.h>, <signal.h>, <poll.h>
+  dnl and others. The workaround is to force preservation of comments
+  dnl through option -C. This ensures all necessary #line directives
+  dnl are present. GCC supports option -C as well.
+  case "$host_os" in
+    aix*) gl_absname_cpp="$ac_cpp -C" ;;
+    *)    gl_absname_cpp="$ac_cpp" ;;
+  esac
+changequote(,)
+  case "$host_os" in
+    mingw*)
+      dnl For the sake of native Windows compilers (excluding gcc),
+      dnl treat backslash as a directory separator, like /.
+      dnl Actually, these compilers use a double-backslash as
+      dnl directory separator, inside the
+      dnl   # line "filename"
+      dnl directives.
+      gl_dirsep_regex='[/\\]'
+      ;;
+    *)
+      gl_dirsep_regex='\/'
+      ;;
+  esac
+  dnl A sed expression that turns a string into a basic regular
+  dnl expression, for use within "/.../".
+  gl_make_literal_regex_sed='s,[]$^\\.*/[],\\&,g'
+  gl_header_literal_regex=`echo '$1' \
+                           | sed -e "$gl_make_literal_regex_sed"`
+  gl_absolute_header_sed="/${gl_dirsep_regex}${gl_header_literal_regex}/"'{
+      s/.*"\(.*'"${gl_dirsep_regex}${gl_header_literal_regex}"'\)".*/\1/
+      s|^/[^/]|//&|
+      p
+      q
+    }'
+changequote([,])
+  dnl eval is necessary to expand gl_absname_cpp.
+  dnl Ultrix and Pyramid sh refuse to redirect output of eval,
+  dnl so use subshell.
+  AS_VAR_SET([gl_cv_absolute_]AS_TR_SH([[$1]]),
+[`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD |
+  sed -n "$gl_absolute_header_sed"`])
+])
diff --git a/m4/gl-openssl.m4 b/m4/gl-openssl.m4
new file mode 100644 (file)
index 0000000..c8f9dd9
--- /dev/null
@@ -0,0 +1,48 @@
+# gl-openssl.m4 serial 3
+dnl Copyright (C) 2013 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_SET_CRYPTO_CHECK_DEFAULT],
+[
+  m4_define([gl_CRYPTO_CHECK_DEFAULT], [$1])
+])
+gl_SET_CRYPTO_CHECK_DEFAULT([no])
+
+AC_DEFUN([gl_CRYPTO_CHECK],
+[
+  m4_divert_once([DEFAULTS], [with_openssl_default='gl_CRYPTO_CHECK_DEFAULT'])
+
+  AC_ARG_WITH([openssl],
+    [AS_HELP_STRING([--with-openssl],
+      [use libcrypto hash routines. Valid ARGs are:
+       'yes', 'no', 'auto' => use if available,
+       'optional' => use if available and warn if not available;
+       default is ']gl_CRYPTO_CHECK_DEFAULT['])],
+    [],
+    [with_openssl=$with_openssl_default])
+
+  if test "x$1" = xMD5; then
+    ALG_header=md5.h
+  else
+    ALG_header=sha.h
+  fi
+
+  LIB_CRYPTO=
+  AC_SUBST([LIB_CRYPTO])
+  if test "x$with_openssl" != xno; then
+    AC_CHECK_LIB([crypto], [$1],
+      [AC_CHECK_HEADERS([openssl/$ALG_header],
+         [LIB_CRYPTO=-lcrypto
+          AC_DEFINE([HAVE_OPENSSL_$1], [1],
+            [Define to 1 if libcrypto is used for $1.])])])
+    if test "x$LIB_CRYPTO" = x; then
+      if test "x$with_openssl" = xyes; then
+        AC_MSG_ERROR([openssl development library not found for $1])
+      elif test "x$with_openssl" = xoptional; then
+        AC_MSG_WARN([openssl development library not found for $1])
+      fi
+    fi
+  fi
+])
index c707e34..3a04c84 100644 (file)
@@ -38,6 +38,7 @@ AC_DEFUN([gl_EARLY],
   m4_pattern_allow([^gl_LIBOBJS$])dnl a variable
   m4_pattern_allow([^gl_LTLIBOBJS$])dnl a variable
   AC_REQUIRE([gl_PROG_AR_RANLIB])
+  # Code from module absolute-header:
   # Code from module alloca-opt:
   # Code from module allocator:
   # Code from module at-internal:
@@ -847,6 +848,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/gettext.h
   lib/gettime.c
   lib/gettimeofday.c
+  lib/gl_openssl.h
   lib/group-member.c
   lib/intprops.h
   lib/inttypes.in.h
@@ -921,6 +923,7 @@ AC_DEFUN([gl_FILE_LIST], [
   lib/verify.h
   lib/xalloc-oversized.h
   m4/00gnulib.m4
+  m4/absolute-header.m4
   m4/acl.m4
   m4/alloca.m4
   m4/byteswap.m4
@@ -953,6 +956,7 @@ AC_DEFUN([gl_FILE_LIST], [
   m4/getopt.m4
   m4/gettime.m4
   m4/gettimeofday.m4
+  m4/gl-openssl.m4
   m4/gnulib-common.m4
   m4/group-member.m4
   m4/include_next.m4
index 108d945..f09dbe6 100644 (file)
@@ -192,56 +192,9 @@ dnl until we can assume autoconf 2.64 or newer.
              if test AS_VAR_GET(gl_header_exists) = yes; then
              AS_VAR_POPDEF([gl_header_exists])
             ])
-               AC_LANG_CONFTEST(
-                 [AC_LANG_SOURCE(
-                    [[#include <]]m4_dquote(m4_defn([gl_HEADER_NAME]))[[>]]
-                  )])
-               dnl AIX "xlc -E" and "cc -E" omit #line directives for header
-               dnl files that contain only a #include of other header files and
-               dnl no non-comment tokens of their own. This leads to a failure
-               dnl to detect the absolute name of <dirent.h>, <signal.h>,
-               dnl <poll.h> and others. The workaround is to force preservation
-               dnl of comments through option -C. This ensures all necessary
-               dnl #line directives are present. GCC supports option -C as well.
-               case "$host_os" in
-                 aix*) gl_absname_cpp="$ac_cpp -C" ;;
-                 *)    gl_absname_cpp="$ac_cpp" ;;
-               esac
-changequote(,)
-               case "$host_os" in
-                 mingw*)
-                   dnl For the sake of native Windows compilers (excluding gcc),
-                   dnl treat backslash as a directory separator, like /.
-                   dnl Actually, these compilers use a double-backslash as
-                   dnl directory separator, inside the
-                   dnl   # line "filename"
-                   dnl directives.
-                   gl_dirsep_regex='[/\\]'
-                   ;;
-                 *)
-                   gl_dirsep_regex='\/'
-                   ;;
-               esac
-               dnl A sed expression that turns a string into a basic regular
-               dnl expression, for use within "/.../".
-               gl_make_literal_regex_sed='s,[]$^\\.*/[],\\&,g'
-changequote([,])
-               gl_header_literal_regex=`echo ']m4_defn([gl_HEADER_NAME])[' \
-                                        | sed -e "$gl_make_literal_regex_sed"`
-               gl_absolute_header_sed="/${gl_dirsep_regex}${gl_header_literal_regex}/"'{
-                   s/.*"\(.*'"${gl_dirsep_regex}${gl_header_literal_regex}"'\)".*/\1/
-changequote(,)dnl
-                   s|^/[^/]|//&|
-changequote([,])dnl
-                   p
-                   q
-                 }'
-               dnl eval is necessary to expand gl_absname_cpp.
-               dnl Ultrix and Pyramid sh refuse to redirect output of eval,
-               dnl so use subshell.
-               AS_VAR_SET(gl_next_header,
-                 ['"'`(eval "$gl_absname_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD |
-                      sed -n "$gl_absolute_header_sed"`'"'])
+           gl_ABSOLUTE_HEADER_ONE(gl_HEADER_NAME)
+           AS_VAR_COPY([gl_header], [gl_cv_absolute_]AS_TR_SH(gl_HEADER_NAME))
+           AS_VAR_SET(gl_next_header, ['"'$gl_header'"'])
           m4_if([$2], [check],
             [else
                AS_VAR_SET(gl_next_header, ['<'gl_HEADER_NAME'>'])
index 0ad6f50..541a26b 100644 (file)
--- a/m4/md5.m4
+++ b/m4/md5.m4
@@ -1,4 +1,4 @@
-# md5.m4 serial 13
+# md5.m4 serial 14
 dnl Copyright (C) 2002-2006, 2008-2013 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,5 +8,7 @@ AC_DEFUN([gl_MD5],
 [
   dnl Prerequisites of lib/md5.c.
   AC_REQUIRE([gl_BIGENDIAN])
-  :
+
+  dnl Determine HAVE_OPENSSL_MD5 and LIB_CRYPTO
+  gl_CRYPTO_CHECK([MD5])
 ])
index 21c775e..57d5256 100644 (file)
@@ -1,4 +1,4 @@
-# sha1.m4 serial 11
+# sha1.m4 serial 12
 dnl Copyright (C) 2002-2006, 2008-2013 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,5 +8,7 @@ AC_DEFUN([gl_SHA1],
 [
   dnl Prerequisites of lib/sha1.c.
   AC_REQUIRE([gl_BIGENDIAN])
-  :
+
+  dnl Determine HAVE_OPENSSL_SHA1 and LIB_CRYPTO
+  gl_CRYPTO_CHECK([SHA1])
 ])
index cbbd17a..3a19467 100644 (file)
@@ -1,4 +1,4 @@
-# sha256.m4 serial 7
+# sha256.m4 serial 8
 dnl Copyright (C) 2005, 2008-2013 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,5 +8,7 @@ AC_DEFUN([gl_SHA256],
 [
   dnl Prerequisites of lib/sha256.c.
   AC_REQUIRE([gl_BIGENDIAN])
-  :
+
+  dnl Determine HAVE_OPENSSL_SHA256 and LIB_CRYPTO
+  gl_CRYPTO_CHECK([SHA256])
 ])
index f4a6bf1..d929195 100644 (file)
@@ -1,4 +1,4 @@
-# sha512.m4 serial 8
+# sha512.m4 serial 9
 dnl Copyright (C) 2005-2006, 2008-2013 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,5 +8,7 @@ AC_DEFUN([gl_SHA512],
 [
   dnl Prerequisites of lib/sha512.c.
   AC_REQUIRE([gl_BIGENDIAN])
-  :
+
+  dnl Determine HAVE_OPENSSL_SHA512 and LIB_CRYPTO
+  gl_CRYPTO_CHECK([SHA512])
 ])
index 5daf1dc..1eba6bb 100644 (file)
@@ -1,5 +1,9 @@
 2013-12-08  Paul Eggert  <eggert@cs.ucla.edu>
 
+       Use libcrypto's checksum implementations if available, for speed.
+       * Makefile.in (LIB_CRYPTO): New macro.
+       (LIBES): Use it.
+
        * frame.h (SET_FRAME_VISIBLE): Now an inline function.
        The macro didn't conform to C99 due to type mismatch,
        which caused compilation failure with Sun C 5.12,
index 7d91928..cef1ba5 100644 (file)
@@ -139,6 +139,7 @@ M17N_FLT_LIBS = @M17N_FLT_LIBS@
 
 LIB_ACL=@LIB_ACL@
 LIB_CLOCK_GETTIME=@LIB_CLOCK_GETTIME@
+LIB_CRYPTO=@LIB_CRYPTO@
 LIB_EACCESS=@LIB_EACCESS@
 LIB_FDATASYNC=@LIB_FDATASYNC@
 LIB_TIMER_TIME=@LIB_TIMER_TIME@
@@ -403,6 +404,7 @@ ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj)
 LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
    $(LIBX_OTHER) $(LIBSOUND) \
    $(RSVG_LIBS) $(IMAGEMAGICK_LIBS) $(LIB_ACL) $(LIB_CLOCK_GETTIME) \
+   $(LIB_CRYPTO) \
    $(LIB_EACCESS) $(LIB_FDATASYNC) $(LIB_TIMER_TIME) $(DBUS_LIBS) \
    $(LIB_EXECINFO) $(XRANDR_LIBS) $(XINERAMA_LIBS) \
    $(LIBXML2_LIBS) $(LIBGPM) $(LIBRESOLV) $(LIBS_SYSTEM) \