diff --git a/configure.ac b/configure.ac index d85b8ebec..e7d8a4bb8 100644 --- a/configure.ac +++ b/configure.ac @@ -1284,26 +1284,57 @@ MIEXT_SHADOW_INC='-I$(top_srcdir)/miext/shadow' MIEXT_SHADOW_LIB='$(top_builddir)/miext/shadow/libshadow.la' CORE_INCS='-I$(top_srcdir)/include -I$(top_builddir)/include' -# OpenSSL used for SHA1 hashing in render/glyph.c, but we don't need all of -# the OpenSSL libraries, just libcrypto -# Some systems have matching functionality in the smaller/simpler libmd -# Builders who want to force a choice can set SHA1_LIB and SHA1_CFLAGS -if test "x$SHA1_LIB" = "x" ; then - AC_CHECK_LIB([md], [SHA1Init], [SHA1_LIB="-lmd" - AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1], - [Use libmd SHA1 functions instead of OpenSSL libcrypto])]) +# SHA1 hashing +AC_ARG_WITH([sha1], + [AS_HELP_STRING([--with-sha1=libmd|libgcrypt|libcrypto], + [choose SHA1 implementation])]) +AC_CHECK_LIB([md], [SHA1Init], [HAVE_LIBMD=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBMD" = xyes; then + with_sha1=libmd fi - -if test "x$SHA1_LIB" = "x" ; then - PKG_CHECK_EXISTS([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes], - [HAVE_OPENSSL_PKC=no]) - if test "x$HAVE_OPENSSL_PKC" = xyes; then - REQUIRED_LIBS="$REQUIRED_LIBS openssl" - else - AC_CHECK_LIB([crypto], [SHA1_Init], [SHA1_LIB="-lcrypto"], - [AC_MSG_ERROR([OpenSSL must be installed in order to build the X server.])]) - fi +if test "x$with_sha1" = xlibmd && test "x$HAVE_LIBMD" != xyes; then + AC_MSG_ERROR([libmd requested but not found]) fi +if test "x$with_sha1" = xlibmd; then + AC_DEFINE([HAVE_SHA1_IN_LIBMD], [1], + [Use libmd SHA1 functions]) + SHA1_LIBS=-lmd +fi +AC_CHECK_LIB([gcrypt], [gcry_md_open], [HAVE_LIBGCRYPT=yes]) +if test "x$with_sha1" = x && test "x$HAVE_LIBGCRYPT" = xyes; then + with_sha1=libgcrypt +fi +if test "x$with_sha1" = xlibgcrypt; then + AC_DEFINE([HAVE_SHA1_IN_LIBGCRYPT], [1], + [Use libgcrypt SHA1 functions]) + SHA1_LIBS=-lgcrypt +fi +# We don't need all of the OpenSSL libraries, just libcrypto +AC_CHECK_LIB([crypto], [SHA1_Init], [HAVE_LIBCRYPTO=yes]) +PKG_CHECK_MODULES([OPENSSL], [openssl], [HAVE_OPENSSL_PKC=yes], + [HAVE_OPENSSL_PKC=no]) +if test "x$HAVE_LIBCRYPTO" = xyes || test "x$HAVE_OPENSSL_PKC" = xyes; then + if test "x$with_sha1" = x; then + with_sha1=libcrypto + fi +else + if test "x$with_sha1" = xlibcrypto; then + AC_MSG_ERROR([OpenSSL libcrypto requested but not found]) + fi +fi +if test "x$with_sha1" = xlibcrypto; then + if test "x$HAVE_LIBCRYPTO" = xyes; then + SHA1_LIBS=-lcrypto + else + SHA1_LIBS="$OPENSSL_LIBS" + SHA1_CFLAGS="$OPENSSL_CFLAGS" + fi +fi +if test "x$with_sha1" = x; then + AC_MSG_ERROR([No suitable SHA1 implementation found]) +fi +AC_SUBST(SHA1_LIBS) +AC_SUBST(SHA1_CFLAGS) PKG_CHECK_MODULES([XSERVERCFLAGS], [$REQUIRED_MODULES $REQUIRED_LIBS]) PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) @@ -1323,9 +1354,9 @@ PKG_CHECK_MODULES([XSERVERLIBS], [$REQUIRED_LIBS]) # XSERVER_SYS_LIBS is the set of out-of-tree libraries which all servers # require. # -XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS} ${SHA1_CFLAGS}" +XSERVER_CFLAGS="${XSERVER_CFLAGS} ${XSERVERCFLAGS_CFLAGS}" XSERVER_LIBS="$DIX_LIB $CONFIG_LIB $MI_LIB $OS_LIB" -XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS} ${SHA1_LIB}" +XSERVER_SYS_LIBS="${XSERVERLIBS_LIBS} ${SYS_LIBS} ${LIBS}" AC_SUBST([XSERVER_LIBS]) AC_SUBST([XSERVER_SYS_LIBS]) diff --git a/include/Makefile.am b/include/Makefile.am index aa5db7d5f..d684f9c2b 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -66,4 +66,5 @@ AM_CFLAGS = $(DIX_CFLAGS) EXTRA_DIST = \ dix-config-apple-verbatim.h \ eventconvert.h eventstr.h \ - protocol-versions.h + protocol-versions.h \ + xsha1.h diff --git a/include/dix-config.h.in b/include/dix-config.h.in index 798d9e73c..7f1fb1836 100644 --- a/include/dix-config.h.in +++ b/include/dix-config.h.in @@ -160,9 +160,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_RPCSVC_DBM_H -/* Define to use libmd SHA1 functions instead of OpenSSL libcrypto */ +/* Define to use libmd SHA1 functions */ #undef HAVE_SHA1_IN_LIBMD +/* Define to use libgcrypt SHA1 functions */ +#undef HAVE_SHA1_IN_LIBGCRYPT + /* Define to 1 if you have the `shmctl64' function. */ #undef HAVE_SHMCTL64 diff --git a/include/xsha1.h b/include/xsha1.h new file mode 100644 index 000000000..aab71067a --- /dev/null +++ b/include/xsha1.h @@ -0,0 +1,19 @@ +#ifndef XSHA1_H +#define XSHA1_H + +/* Initialize SHA1 computation. Returns NULL on error. */ +void *x_sha1_init(void); + +/* + * Add some data to be hashed. ctx is the value returned by x_sha1_init() + * Returns 0 on error, 1 on success. + */ +int x_sha1_update(void *ctx, void *data, int size); + +/* + * Place the hash in result, and free ctx. + * Returns 0 on error, 1 on success. + */ +int x_sha1_final(void *ctx, unsigned char result[20]); + +#endif diff --git a/os/Makefile.am b/os/Makefile.am index a7f34a5b8..9902f045c 100644 --- a/os/Makefile.am +++ b/os/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libos.la -AM_CFLAGS = $(DIX_CFLAGS) +AM_CFLAGS = $(DIX_CFLAGS) $(SHA1_CFLAGS) SECURERPC_SRCS = rpcauth.c XDMCP_SRCS = xdmcp.c @@ -22,9 +22,11 @@ libos_la_SOURCES = \ strcasecmp.c \ strcasestr.c \ xdmauth.c \ + xsha1.c \ xstrans.c \ xprintf.c \ $(XORG_SRCS) +libos_la_LIBADD = @SHA1_LIBS@ if SECURE_RPC libos_la_SOURCES += $(SECURERPC_SRCS) diff --git a/os/xsha1.c b/os/xsha1.c new file mode 100644 index 000000000..723521e05 --- /dev/null +++ b/os/xsha1.c @@ -0,0 +1,113 @@ +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "os.h" +#include "xsha1.h" + +#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */ + +# include + +void *x_sha1_init(void) +{ + SHA1_CTX *ctx = xalloc(sizeof(*ctx)); + if (!ctx) + return NULL; + SHA1Init(ctx); + return ctx; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + SHA1_CTX *sha1_ctx = ctx; + SHA1Update(sha1_ctx, data, size); + return 1; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + SHA1_CTX *sha1_ctx = ctx; + SHA1Final(result, sha1_ctx); + xfree(sha1_ctx); + return 1; +} + +#elif defined(HAVE_SHA1_IN_LIBGCRYPT) /* Use libgcrypt for SHA1 */ + +# include + +void *x_sha1_init(void) +{ + static int init; + gcry_md_hd_t h; + gcry_error_t err; + + if (!init) { + if (!gcry_check_version(NULL)) + return NULL; + gcry_control(GCRYCTL_DISABLE_SECMEM, 0); + gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); + init = 1; + } + + err = gcry_md_open(&h, GCRY_MD_SHA1, 0); + if (err) + return NULL; + return h; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + gcry_md_hd_t h = ctx; + gcry_md_write(h, data, size); + return 1; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + gcry_md_hd_t h = ctx; + memcpy(result, gcry_md_read(h, GCRY_MD_SHA1), 20); + gcry_md_close(h); + return 1; +} + +#else /* Use OpenSSL's libcrypto */ + +# include /* buggy openssl/sha.h wants size_t */ +# include + +void *x_sha1_init(void) +{ + int ret; + SHA_CTX *ctx = xalloc(sizeof(*ctx)); + if (!ctx) + return NULL; + ret = SHA1_Init(ctx); + if (!ret) { + xfree(ctx); + return NULL; + } + return ctx; +} + +int x_sha1_update(void *ctx, void *data, int size) +{ + int ret; + SHA_CTX *sha_ctx = ctx; + ret = SHA1_Update(sha_ctx, data, size); + if (!ret) + xfree(sha_ctx); + return ret; +} + +int x_sha1_final(void *ctx, unsigned char result[20]) +{ + int ret; + SHA_CTX *sha_ctx = ctx; + ret = SHA1_Final(result, sha_ctx); + xfree(sha_ctx); + return ret; +} + +#endif diff --git a/render/glyph.c b/render/glyph.c index 7fcdfd9d1..0b864ad4d 100644 --- a/render/glyph.c +++ b/render/glyph.c @@ -26,12 +26,7 @@ #include #endif -#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */ -# include -#else /* Use OpenSSL's libcrypto */ -# include /* buggy openssl/sha.h wants size_t */ -# include -#endif +#include "xsha1.h" #include "misc.h" #include "scrnintstr.h" @@ -198,34 +193,21 @@ HashGlyph (xGlyphInfo *gi, unsigned long size, unsigned char sha1[20]) { -#ifdef HAVE_SHA1_IN_LIBMD /* Use libmd for SHA1 */ - SHA1_CTX ctx; - - SHA1Init (&ctx); - SHA1Update (&ctx, gi, sizeof (xGlyphInfo)); - SHA1Update (&ctx, bits, size); - SHA1Final (sha1, &ctx); -#else /* Use OpenSSL's libcrypto */ - SHA_CTX ctx; + void *ctx = x_sha1_init(); int success; - success = SHA1_Init (&ctx); - if (! success) + if (!ctx) return BadAlloc; - success = SHA1_Update (&ctx, gi, sizeof (xGlyphInfo)); - if (! success) + success = x_sha1_update(ctx, gi, sizeof(xGlyphInfo)); + if (!success) return BadAlloc; - - success = SHA1_Update (&ctx, bits, size); - if (! success) + success = x_sha1_update(ctx, bits, size); + if (!success) return BadAlloc; - - success = SHA1_Final (sha1, &ctx); - if (! success) + success = x_sha1_final(ctx, sha1); + if (!success) return BadAlloc; -#endif - return Success; }