[Mesa-dev] [PATCH] util: import sha1 implementation from OpenBSD

Jonathan Gray jsg at jsg.id.au
Sat Jan 14 06:25:47 UTC 2017


On Fri, Jan 13, 2017 at 04:51:31PM +0000, Emil Velikov wrote:
> From: Emil Velikov <emil.velikov at collabora.com>
> 
> At the moment we support 5+ different implementations each with varying
> amount of bugs - from thread safely problems [1], to outright broken
> implementation(s) [2]
> 
> In order to accommodate these we have 150+ lines of configure script and
> extra two configure toggles. Whist an actual implementation being
> ~200loc and our current compat wrapping ~250.
> 
> Let's not forget that different people use different code paths, thus
> effectively makes it harder to test and debug since the default
> implementation is automatically detected.
> 
> To minimise all these lovely experiences, import the "100% Public
> Domain" OpenBSD sha1 implementation. Clearly document any changes needed
> to get building correctly, since many/most of those can be upstreamed
> making future syncs easier.

I had feared that this would somehow collide with the symbols
in libc but it seems to build and run xorg/glxgears at least
on broadwell with i965.

Patches for OpenBSD go to tech@ and you should look at how portable
openssh and libressl handle systems that lack functions like
explicit_bzero, autoconf detects systems that lack functions or are
known to have broken implementations and alternate versions are
provided.  Damien Miller described how this is handled for ssh in
https://www.openbsd.org/papers/portability.pdf
https://www.openbsd.org/papers/auug2005-portability/

The attribute could also be checked in autoconf as is already done
for various other attributes.

Other parts seem odd, posix defines size_t as being in sys/types.h
not stddef.h for example.

u_int* are bsd types which predate c99 types, I could see an
argument being made for changing the types there but it
would likely have to cover all the other hashes as well,
not just sha1.

> 
> As an added bonus this will avoid all the 'fun' experiences trying to
> integrate it with the Android and SCons builds.
> 
> Bugzilla [1]: https://bugs.freedesktop.org/show_bug.cgi?id=94904
> Bugzilla [2]: https://bugs.freedesktop.org/show_bug.cgi?id=97967
> Cc: Mark Janes <mark.a.janes at intel.com>
> Cc: Vinson Lee <vlee at freedesktop.org>
> Cc: Tapani P??lli <tapani.palli at intel.com>
> Cc: Jonathan Gray <jsg at jsg.id.au>
> Signed-off-by: Emil Velikov <emil.velikov at collabora.com>
> ---
>  configure.ac                         | 161 +----------------------
>  src/compiler/glsl/tests/cache_test.c |   5 -
>  src/mesa/main/shaderapi.c            |   6 -
>  src/util/Makefile.am                 |   3 -
>  src/util/Makefile.sources            |   2 +
>  src/util/SConscript                  |   5 -
>  src/util/disk_cache.c                |   4 -
>  src/util/disk_cache.h                |  42 ------
>  src/util/mesa-sha1.c                 | 242 +----------------------------------
>  src/util/sha1/README                 |  55 ++++++++
>  src/util/sha1/sha1.c                 | 173 +++++++++++++++++++++++++
>  src/util/sha1/sha1.h                 |  47 +++++++
>  12 files changed, 279 insertions(+), 466 deletions(-)
>  create mode 100644 src/util/sha1/README
>  create mode 100644 src/util/sha1/sha1.c
>  create mode 100644 src/util/sha1/sha1.h
> 
> diff --git a/configure.ac b/configure.ac
> index 459f3e8b0a..5772b378c7 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -9,7 +9,6 @@ dnl Copyright ?? 2009-2014 Jon TURNEY
>  dnl Copyright ?? 2011-2012 Benjamin Franzke
>  dnl Copyright ?? 2008-2014 David Airlie
>  dnl Copyright ?? 2009-2013 Brian Paul
> -dnl Copyright ?? 2003-2007 Keith Packard, Daniel Stone
>  dnl
>  dnl Permission is hereby granted, free of charge, to any person obtaining a
>  dnl copy of this software and associated documentation files (the "Software"),
> @@ -1432,151 +1431,6 @@ if test "x$enable_gallium_osmesa" = xyes; then
>      fi
>  fi
>  
> -# SHA1 hashing
> -AC_ARG_WITH([sha1],
> -        [AS_HELP_STRING([--with-sha1=libc|libmd|libnettle|libgcrypt|libcrypto|libsha1|CommonCrypto|CryptoAPI],
> -        [choose SHA1 implementation])])
> -case "x$with_sha1" in
> -x | xlibc | xlibmd | xlibnettle | xlibgcrypt | xlibcrypto | xlibsha1 | xCommonCrypto | xCryptoAPI)
> -  ;;
> -*)
> -        AC_MSG_ERROR([Illegal value for --with-sha1: $with_sha1])
> -esac
> -
> -AC_CHECK_FUNC([SHA1Init], [HAVE_SHA1_IN_LIBC=yes])
> -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_LIBC" = xyes; then
> -	with_sha1=libc
> -fi
> -if test "x$with_sha1" = xlibc && test "x$HAVE_SHA1_IN_LIBC" != xyes; then
> -	AC_MSG_ERROR([sha1 in libc requested but not found])
> -fi
> -if test "x$with_sha1" = xlibc; then
> -	AC_DEFINE([HAVE_SHA1_IN_LIBC], [1],
> -		[Use libc SHA1 functions])
> -	SHA1_LIBS=""
> -fi
> -AC_CHECK_FUNC([CC_SHA1_Init], [HAVE_SHA1_IN_COMMONCRYPTO=yes])
> -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_COMMONCRYPTO" = xyes; then
> -	with_sha1=CommonCrypto
> -fi
> -if test "x$with_sha1" = xCommonCrypto && test "x$HAVE_SHA1_IN_COMMONCRYPTO" != xyes; then
> -	AC_MSG_ERROR([CommonCrypto requested but not found])
> -fi
> -if test "x$with_sha1" = xCommonCrypto; then
> -	AC_DEFINE([HAVE_SHA1_IN_COMMONCRYPTO], [1],
> -		[Use CommonCrypto SHA1 functions])
> -	SHA1_LIBS=""
> -fi
> -dnl stdcall functions cannot be tested with AC_CHECK_LIB
> -AC_CHECK_HEADER([wincrypt.h], [HAVE_SHA1_IN_CRYPTOAPI=yes], [], [#include <windows.h>])
> -if test "x$with_sha1" = x && test "x$HAVE_SHA1_IN_CRYPTOAPI" = xyes; then
> -	with_sha1=CryptoAPI
> -fi
> -if test "x$with_sha1" = xCryptoAPI && test "x$HAVE_SHA1_IN_CRYPTOAPI" != xyes; then
> -	AC_MSG_ERROR([CryptoAPI requested but not found])
> -fi
> -if test "x$with_sha1" = xCryptoAPI; then
> -	AC_DEFINE([HAVE_SHA1_IN_CRYPTOAPI], [1],
> -		[Use CryptoAPI SHA1 functions])
> -	SHA1_LIBS=""
> -fi
> -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$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
> -PKG_CHECK_MODULES([LIBSHA1], [libsha1], [HAVE_LIBSHA1=yes], [HAVE_LIBSHA1=no])
> -if test "x$with_sha1" = x && test "x$HAVE_LIBSHA1" = xyes; then
> -   with_sha1=libsha1
> -fi
> -if test "x$with_sha1" = xlibsha1 && test "x$HAVE_LIBSHA1" != xyes; then
> -	AC_MSG_ERROR([libsha1 requested but not found])
> -fi
> -if test "x$with_sha1" = xlibsha1; then
> -	AC_DEFINE([HAVE_SHA1_IN_LIBSHA1], [1],
> -	          [Use libsha1 for SHA1])
> -	SHA1_LIBS=-lsha1
> -fi
> -AC_CHECK_LIB([nettle], [nettle_sha1_init], [HAVE_LIBNETTLE=yes])
> -if test "x$with_sha1" = x && test "x$HAVE_LIBNETTLE" = xyes; then
> -	with_sha1=libnettle
> -fi
> -if test "x$with_sha1" = xlibnettle && test "x$HAVE_LIBNETTLE" != xyes; then
> -	AC_MSG_ERROR([libnettle requested but not found])
> -fi
> -if test "x$with_sha1" = xlibnettle; then
> -	AC_DEFINE([HAVE_SHA1_IN_LIBNETTLE], [1],
> -	          [Use libnettle SHA1 functions])
> -	SHA1_LIBS=-lnettle
> -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 && test "x$HAVE_LIBGCRYPT" != xyes; then
> -	AC_MSG_ERROR([libgcrypt requested but not found])
> -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
> -AC_MSG_CHECKING([for SHA1 implementation])
> -AC_MSG_RESULT([$with_sha1])
> -AC_SUBST(SHA1_LIBS)
> -AC_SUBST(SHA1_CFLAGS)
> -
> -# Enable a define for SHA1
> -if test "x$with_sha1" != "x"; then
> -	DEFINES="$DEFINES -DHAVE_SHA1"
> -fi
> -
> -# Allow user to configure out the shader-cache feature
> -AC_ARG_ENABLE([shader-cache],
> -    AS_HELP_STRING([--disable-shader-cache], [Disable binary shader cache]),
> -    [enable_shader_cache="$enableval"],
> -    [if test "x$with_sha1" != "x"; then
> -        enable_shader_cache=yes
> -     else
> -        enable_shader_cache=no
> -     fi])
> -if test "x$with_sha1" = "x"; then
> -    if test "x$enable_shader_cache" = "xyes"; then
> -        AC_MSG_ERROR([Cannot enable shader cache (no SHA-1 implementation found)])
> -    fi
> -fi
> -if test "x$enable_shader_cache" = "xyes"; then
> -   AC_DEFINE([ENABLE_SHADER_CACHE], [1], [Enable shader cache])
> -fi
> -
>  if test "x$enable_dri" = xyes; then
>      if test "$enable_static" = yes; then
>          AC_MSG_ERROR([Cannot use static libraries for DRI drivers])
> @@ -1899,9 +1753,6 @@ if test -n "$with_vulkan_drivers"; then
>              if test "x$HAVE_I965_DRI" != xyes; then
>                  AC_MSG_ERROR([Intel Vulkan driver requires the i965 dri driver])
>              fi
> -            if test "x$with_sha1" == "x"; then
> -                AC_MSG_ERROR([Intel Vulkan driver requires SHA1])
> -            fi
>              HAVE_INTEL_VULKAN=yes;
>  
>              ;;
> @@ -1909,10 +1760,7 @@ if test -n "$with_vulkan_drivers"; then
>              PKG_CHECK_MODULES([AMDGPU], [libdrm_amdgpu >= $LIBDRM_AMDGPU_REQUIRED])
>              radeon_llvm_check $LLVM_REQUIRED_RADV "radv"
>              HAVE_RADEON_VULKAN=yes;
> -            if test "x$with_sha1" == "x"; then
> -                AC_MSG_ERROR([radv vulkan driver requires SHA1])
> -            fi
> -	    ;;
> +            ;;
>          *)
>              AC_MSG_ERROR([Vulkan driver '$driver' does not exist])
>              ;;
> @@ -3001,13 +2849,6 @@ else
>      echo "        HUD lmsensors:   yes"
>  fi
>  
> -dnl Shader cache
> -echo ""
> -echo "        Shader cache:    $enable_shader_cache"
> -if test "x$enable_shader_cache" = "xyes"; then
> -    echo "        With SHA1 from:  $with_sha1"
> -fi
> -
>  dnl Libraries
>  echo ""
>  echo "        Shared libs:     $enable_shared"
> diff --git a/src/compiler/glsl/tests/cache_test.c b/src/compiler/glsl/tests/cache_test.c
> index 0ef05aacb2..f53ef0de14 100644
> --- a/src/compiler/glsl/tests/cache_test.c
> +++ b/src/compiler/glsl/tests/cache_test.c
> @@ -37,8 +37,6 @@
>  
>  bool error = false;
>  
> -#ifdef ENABLE_SHADER_CACHE
> -
>  static void
>  expect_equal(uint64_t actual, uint64_t expected, const char *test)
>  {
> @@ -380,12 +378,10 @@ test_put_key_and_get_key(void)
>  
>     disk_cache_destroy(cache);
>  }
> -#endif /* ENABLE_SHADER_CACHE */
>  
>  int
>  main(void)
>  {
> -#ifdef ENABLE_SHADER_CACHE
>     int err;
>  
>     test_disk_cache_create();
> @@ -396,7 +392,6 @@ main(void)
>  
>     err = rmrf_local(CACHE_TEST_TMP);
>     expect_equal(err, 0, "Removing " CACHE_TEST_TMP " again");
> -#endif /* ENABLE_SHADER_CACHE */
>  
>     return error ? 1 : 0;
>  }
> diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
> index fe4cf1bed2..96a4ce0834 100644
> --- a/src/mesa/main/shaderapi.c
> +++ b/src/mesa/main/shaderapi.c
> @@ -1612,7 +1612,6 @@ _mesa_LinkProgram(GLuint programObj)
>                                                             "glLinkProgram"));
>  }
>  
> -#if defined(HAVE_SHA1)
>  /**
>   * Generate a SHA-1 hash value string for given source string.
>   */
> @@ -1723,7 +1722,6 @@ read_shader(const gl_shader_stage stage, const char *source)
>  
>     return buffer;
>  }
> -#endif /* HAVE_SHA1 */
>  
>  /**
>   * Called via glShaderSource() and glShaderSourceARB() API functions.
> @@ -1740,9 +1738,7 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
>     GLcharARB *source;
>     struct gl_shader *sh;
>  
> -#if defined(HAVE_SHA1)
>     GLcharARB *replacement;
> -#endif /* HAVE_SHA1 */
>  
>     sh = _mesa_lookup_shader_err(ctx, shaderObj, "glShaderSourceARB");
>     if (!sh)
> @@ -1799,7 +1795,6 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
>     source[totalLength - 1] = '\0';
>     source[totalLength - 2] = '\0';
>  
> -#if defined(HAVE_SHA1)
>     /* Dump original shader source to MESA_SHADER_DUMP_PATH and replace
>      * if corresponding entry found from MESA_SHADER_READ_PATH.
>      */
> @@ -1810,7 +1805,6 @@ _mesa_ShaderSource(GLuint shaderObj, GLsizei count,
>        free(source);
>        source = replacement;
>     }
> -#endif /* HAVE_SHA1 */
>  
>     shader_source(sh, source);
>  
> diff --git a/src/util/Makefile.am b/src/util/Makefile.am
> index 093589163b..32316b038f 100644
> --- a/src/util/Makefile.am
> +++ b/src/util/Makefile.am
> @@ -36,7 +36,6 @@ libmesautil_la_CPPFLAGS = \
>  	-I$(top_srcdir)/src/mesa \
>  	-I$(top_srcdir)/src/gallium/include \
>  	-I$(top_srcdir)/src/gallium/auxiliary \
> -	$(SHA1_CFLAGS) \
>  	$(VISIBILITY_CFLAGS) \
>  	$(MSVC2013_COMPAT_CFLAGS)
>  
> @@ -44,8 +43,6 @@ libmesautil_la_SOURCES = \
>  	$(MESA_UTIL_FILES) \
>  	$(MESA_UTIL_GENERATED_FILES)
>  
> -libmesautil_la_LIBADD = $(SHA1_LIBS)
> -
>  roundeven_test_LDADD = -lm
>  
>  check_PROGRAMS = u_atomic_test roundeven_test
> diff --git a/src/util/Makefile.sources b/src/util/Makefile.sources
> index d2ae5e734d..a68a5fe22f 100644
> --- a/src/util/Makefile.sources
> +++ b/src/util/Makefile.sources
> @@ -19,6 +19,8 @@ MESA_UTIL_FILES :=	\
>  	macros.h \
>  	mesa-sha1.c \
>  	mesa-sha1.h \
> +	sha1/sha1.c \
> +	sha1/sha1.h \
>  	ralloc.c \
>  	ralloc.h \
>  	register_allocate.c \
> diff --git a/src/util/SConscript b/src/util/SConscript
> index 73f3430397..7e447f6e03 100644
> --- a/src/util/SConscript
> +++ b/src/util/SConscript
> @@ -33,11 +33,6 @@ mesautil_sources = (
>      source_lists['MESA_UTIL_GENERATED_FILES']
>  )
>  
> -# XXX We don't yet have scons support for detecting any of the various
> -# HAVE_SHA1_* definitions, so for now simply disable the shader cache.
> -if False:
> -    mesautil_sources += source_lists['MESA_UTIL_SHADER_CACHE_FILES']
> -
>  mesautil = env.ConvenienceLibrary(
>      target = 'mesautil',
>      source = mesautil_sources,
> diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c
> index 80dc7881d5..76bdfe8e8b 100644
> --- a/src/util/disk_cache.c
> +++ b/src/util/disk_cache.c
> @@ -21,8 +21,6 @@
>   * IN THE SOFTWARE.
>   */
>  
> -#ifdef ENABLE_SHADER_CACHE
> -
>  #include <ctype.h>
>  #include <string.h>
>  #include <stdlib.h>
> @@ -707,5 +705,3 @@ disk_cache_has_key(struct disk_cache *cache, cache_key key)
>  
>     return memcmp(entry, key, CACHE_KEY_SIZE) == 0;
>  }
> -
> -#endif
> diff --git a/src/util/disk_cache.h b/src/util/disk_cache.h
> index 7e9cb809b5..0b20665e97 100644
> --- a/src/util/disk_cache.h
> +++ b/src/util/disk_cache.h
> @@ -40,8 +40,6 @@ struct disk_cache;
>  
>  /* Provide inlined stub functions if the shader cache is disabled. */
>  
> -#ifdef ENABLE_SHADER_CACHE
> -
>  /**
>   * Create a new cache object.
>   *
> @@ -131,46 +129,6 @@ disk_cache_put_key(struct disk_cache *cache, cache_key key);
>  bool
>  disk_cache_has_key(struct disk_cache *cache, cache_key key);
>  
> -#else
> -
> -static inline struct disk_cache *
> -disk_cache_create(void)
> -{
> -   return NULL;
> -}
> -
> -static inline void
> -disk_cache_destroy(struct disk_cache *cache) {
> -   return;
> -}
> -
> -static inline void
> -disk_cache_put(struct disk_cache *cache, cache_key key,
> -          const void *data, size_t size)
> -{
> -   return;
> -}
> -
> -static inline uint8_t *
> -disk_cache_get(struct disk_cache *cache, cache_key key, size_t *size)
> -{
> -   return NULL;
> -}
> -
> -static inline void
> -disk_cache_put_key(struct disk_cache *cache, cache_key key)
> -{
> -   return;
> -}
> -
> -static inline bool
> -disk_cache_has_key(struct disk_cache *cache, cache_key key)
> -{
> -   return false;
> -}
> -
> -#endif /* ENABLE_SHADER_CACHE */
> -
>  #ifdef __cplusplus
>  }
>  #endif
> diff --git a/src/util/mesa-sha1.c b/src/util/mesa-sha1.c
> index b6a192f4da..e8f1bad22f 100644
> --- a/src/util/mesa-sha1.c
> +++ b/src/util/mesa-sha1.c
> @@ -24,15 +24,9 @@
>   * DEALINGS IN THE SOFTWARE.
>   */
>  
> +#include "sha1/sha1.h"
>  #include "mesa-sha1.h"
>  
> -#ifdef HAVE_SHA1
> -
> -#if defined(HAVE_SHA1_IN_LIBMD)  /* Use libmd for SHA1 */ \
> -	|| defined(HAVE_SHA1_IN_LIBC)   /* Use libc for SHA1 */
> -
> -#include <sha1.h>
> -
>  struct mesa_sha1 *
>  _mesa_sha1_init(void)
>  {
> @@ -64,238 +58,6 @@ _mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
>     return 1;
>  }
>  
> -#elif defined(HAVE_SHA1_IN_COMMONCRYPTO)        /* Use CommonCrypto for SHA1 */
> -
> -#include <CommonCrypto/CommonDigest.h>
> -
> -struct mesa_sha1 *
> -_mesa_sha1_init(void)
> -{
> -   CC_SHA1_CTX *ctx = malloc(sizeof(*ctx));
> -
> -   if (!ctx)
> -      return NULL;
> -
> -   CC_SHA1_Init(ctx);
> -   return (struct mesa_sha1 *) ctx;
> -}
> -
> -int
> -_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
> -{
> -   CC_SHA1_CTX *sha1_ctx = (CC_SHA1_CTX *) ctx;
> -
> -   CC_SHA1_Update(sha1_ctx, data, size);
> -   return 1;
> -}
> -
> -int
> -_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
> -{
> -   CC_SHA1_CTX *sha1_ctx = (CC_SHA1_CTX *) ctx;
> -
> -   CC_SHA1_Final(result, sha1_ctx);
> -   free(sha1_ctx);
> -   return 1;
> -}
> -
> -#elif defined(HAVE_SHA1_IN_CRYPTOAPI)        /* Use CryptoAPI for SHA1 */
> -
> -#define WIN32_LEAN_AND_MEAN
> -#include <windows.h>
> -#include <wincrypt.h>
> -
> -static HCRYPTPROV hProv;
> -
> -struct mesa_sha1 *
> -_mesa_sha1_init(void)
> -{
> -   HCRYPTHASH *ctx = malloc(sizeof(*ctx));
> -
> -   if (!ctx)
> -      return NULL;
> -
> -   CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
> -   CryptCreateHash(hProv, CALG_SHA1, 0, 0, ctx);
> -   return (struct mesa_sha1 *) ctx;
> -}
> -
> -int
> -_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
> -{
> -   HCRYPTHASH *hHash = (HCRYPTHASH *) ctx;
> -
> -   CryptHashData(*hHash, data, size, 0);
> -   return 1;
> -}
> -
> -int
> -_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
> -{
> -   HCRYPTHASH *hHash = (HCRYPTHASH *) ctx;
> -   DWORD len = 20;
> -
> -   CryptGetHashParam(*hHash, HP_HASHVAL, result, &len, 0);
> -   CryptDestroyHash(*hHash);
> -   CryptReleaseContext(hProv, 0);
> -   free(ctx);
> -   return 1;
> -}
> -
> -#elif defined(HAVE_SHA1_IN_LIBNETTLE)   /* Use libnettle for SHA1 */
> -
> -#include <nettle/sha.h>
> -
> -struct mesa_sha1 *
> -_mesa_sha1_init(void)
> -{
> -   struct sha1_ctx *ctx = malloc(sizeof(*ctx));
> -
> -   if (!ctx)
> -      return NULL;
> -   sha1_init(ctx);
> -   return (struct mesa_sha1 *) ctx;
> -}
> -
> -int
> -_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
> -{
> -   sha1_update((struct sha1_ctx *) ctx, size, data);
> -   return 1;
> -}
> -
> -int
> -_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
> -{
> -   sha1_digest((struct sha1_ctx *) ctx, 20, result);
> -   free(ctx);
> -   return 1;
> -}
> -
> -#elif defined(HAVE_SHA1_IN_LIBGCRYPT)   /* Use libgcrypt for SHA1 */
> -
> -#include <gcrypt.h>
> -#include "c11/threads.h"
> -
> -static void _mesa_libgcrypt_init(void)
> -{
> -   if (!gcry_check_version(NULL))
> -      return;
> -
> -   gcry_control(GCRYCTL_DISABLE_SECMEM, 0);
> -   gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
> -}
> -
> -struct mesa_sha1 *
> -_mesa_sha1_init(void)
> -{
> -   static once_flag flag = ONCE_FLAG_INIT;
> -   gcry_md_hd_t h;
> -   gcry_error_t err;
> -
> -   call_once(&flag, _mesa_libgcrypt_init);
> -
> -   err = gcry_md_open(&h, GCRY_MD_SHA1, 0);
> -   if (err)
> -      return NULL;
> -   return (struct mesa_sha1 *) h;
> -}
> -
> -int
> -_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
> -{
> -   gcry_md_hd_t h = (gcry_md_hd_t) ctx;
> -
> -   gcry_md_write(h, data, size);
> -   return 1;
> -}
> -
> -int
> -_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
> -{
> -   gcry_md_hd_t h = (gcry_md_hd_t) ctx;
> -
> -   memcpy(result, gcry_md_read(h, GCRY_MD_SHA1), 20);
> -   gcry_md_close(h);
> -   return 1;
> -}
> -
> -#elif defined(HAVE_SHA1_IN_LIBSHA1)     /* Use libsha1 */
> -
> -#include <libsha1.h>
> -
> -struct mesa_sha1 *
> -_mesa_sha1_init(void)
> -{
> -   sha1_ctx *ctx = malloc(sizeof(*ctx));
> -
> -   if (!ctx)
> -      return NULL;
> -   sha1_begin(ctx);
> -   return (struct mesa_sha1 *) ctx;
> -}
> -
> -int
> -_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
> -{
> -   sha1_hash(data, size, (sha1_ctx *) ctx);
> -   return 1;
> -}
> -
> -int
> -_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
> -{
> -   sha1_end(result, (sha1_ctx *) ctx);
> -   free(ctx);
> -   return 1;
> -}
> -
> -#else                           /* Use OpenSSL's libcrypto */
> -
> -#include <stddef.h>             /* buggy openssl/sha.h wants size_t */
> -#include <openssl/sha.h>
> -
> -struct mesa_sha1 *
> -_mesa_sha1_init(void)
> -{
> -   int ret;
> -   SHA_CTX *ctx = malloc(sizeof(*ctx));
> -
> -   if (!ctx)
> -      return NULL;
> -   ret = SHA1_Init(ctx);
> -   if (!ret) {
> -      free(ctx);
> -      return NULL;
> -   }
> -   return (struct mesa_sha1 *) ctx;
> -}
> -
> -int
> -_mesa_sha1_update(struct mesa_sha1 *ctx, const void *data, int size)
> -{
> -   int ret;
> -   SHA_CTX *sha_ctx = (SHA_CTX *) ctx;
> -
> -   ret = SHA1_Update(sha_ctx, data, size);
> -   if (!ret)
> -      free(sha_ctx);
> -   return ret;
> -}
> -
> -int
> -_mesa_sha1_final(struct mesa_sha1 *ctx, unsigned char result[20])
> -{
> -   int ret;
> -   SHA_CTX *sha_ctx = (SHA_CTX *) ctx;
> -
> -   ret = SHA1_Final(result, (SHA_CTX *) sha_ctx);
> -   free(sha_ctx);
> -   return ret;
> -}
> -
> -#endif
> -
>  void
>  _mesa_sha1_compute(const void *data, size_t size, unsigned char result[20])
>  {
> @@ -320,5 +82,3 @@ _mesa_sha1_format(char *buf, const unsigned char *sha1)
>  
>     return buf;
>  }
> -
> -#endif
> diff --git a/src/util/sha1/README b/src/util/sha1/README
> new file mode 100644
> index 0000000000..8a1b9864e1
> --- /dev/null
> +++ b/src/util/sha1/README
> @@ -0,0 +1,55 @@
> +This local copy of a SHA1 implementation based on the sources below.
> +
> +Why:
> + - Some libraries suffer from race condition and other issues. For example see
> +commit ade3108bb5b0 ("util: Fix race condition on libgcrypt initialization").
> +
> + - Fold the handling and detection of _eight_ implementations at configure
> +stage and _seven_ different codepaths.
> +
> + - Have a single, uniform, code used by developers, testers and users.
> +
> + - Avoid conflicts when using software which ships with it's own SHA1 library.
> +The latter of which conflicting with the one mesa is build against.
> +
> +
> +
> +Source:
> +The SHA1 implementation is copied verbatim from the following links.
> +At the time of checkout HEAD is 1.25 and 1.24 respectively.
> +
> +http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/lib/libc/hash/sha1.c?rev=HEAD
> +http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/include/sha1.h?rev=HEAD
> +
> +
> +Notes:
> + - The files should not have any local changes. If there are any they should be
> +clearly documented below and one should aim to upstream them where possible.
> + 
> + - Files will be periodically syncronised with the respective upstream sources.
> +Updates will be made regularly, but since the code is _not_ aimed as a
> +cryptography solution any issues found should not be considered security ones.
> +
> +
> +Local changes:
> + - Removed __bounded__ attribute qualifiers. Unavailable on platforms targeted
> +by Mesa. Upstream status: TBD (N/A ?)
> +
> + - Pick the sha1.h header from the current folder, by using "" over <> in the
> +include directive. Upstream status: TBD
> +
> + - Remove unused function prototypes - SHA1End, SHA1File, SHA1FileChunk and
> +SHA1Data. Upstream status: TBD
> +
> + - Use stdint.h integer types - u_int{8,16,32}_t -> uint{8,16,32}_t and
> +u_int -> uint32_t, change header include. Upstream status: TBD
> +
> + - Revert sha1.c rev 1.26 change (introduce DEF_WEAK).
> +Upstream status: TBD (N/A ?)
> +
> + - Add stdint.h include in sha1.h for uint*_t types. Upstream status: TBD
> +
> + - Add stddef.h include in sha1.h for size_t type. Upstream status: TBD
> +
> + - Use memset over explicit_bzero, since memset_s once isn't widely available.
> +Upstream status: TBD (N/A ?)
> diff --git a/src/util/sha1/sha1.c b/src/util/sha1/sha1.c
> new file mode 100644
> index 0000000000..ef59ea1dfc
> --- /dev/null
> +++ b/src/util/sha1/sha1.c
> @@ -0,0 +1,173 @@
> +/*	$OpenBSD: sha1.c,v 1.26 2015/09/11 09:18:27 guenther Exp $	*/
> +
> +/*
> + * SHA-1 in C
> + * By Steve Reid <steve at edmweb.com>
> + * 100% Public Domain
> + *
> + * Test Vectors (from FIPS PUB 180-1)
> + * "abc"
> + *   A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
> + * "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
> + *   84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
> + * A million repetitions of "a"
> + *   34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
> + */
> +
> +#include <stdint.h>
> +#include <string.h>
> +#include "sha1.h"
> +
> +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
> +
> +/*
> + * blk0() and blk() perform the initial expand.
> + * I got the idea of expanding during the round function from SSLeay
> + */
> +#if BYTE_ORDER == LITTLE_ENDIAN
> +# define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
> +    |(rol(block->l[i],8)&0x00FF00FF))
> +#else
> +# define blk0(i) block->l[i]
> +#endif
> +#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
> +    ^block->l[(i+2)&15]^block->l[i&15],1))
> +
> +/*
> + * (R0+R1), R2, R3, R4 are the different operations (rounds) used in SHA1
> + */
> +#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
> +#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
> +#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
> +#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
> +#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
> +
> +typedef union {
> +	uint8_t c[64];
> +	uint32_t l[16];
> +} CHAR64LONG16;
> +
> +/*
> + * Hash a single 512-bit block. This is the core of the algorithm.
> + */
> +void
> +SHA1Transform(uint32_t state[5], const uint8_t buffer[SHA1_BLOCK_LENGTH])
> +{
> +	uint32_t a, b, c, d, e;
> +	uint8_t workspace[SHA1_BLOCK_LENGTH];
> +	CHAR64LONG16 *block = (CHAR64LONG16 *)workspace;
> +
> +	(void)memcpy(block, buffer, SHA1_BLOCK_LENGTH);
> +
> +	/* Copy context->state[] to working vars */
> +	a = state[0];
> +	b = state[1];
> +	c = state[2];
> +	d = state[3];
> +	e = state[4];
> +
> +	/* 4 rounds of 20 operations each. Loop unrolled. */
> +	R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
> +	R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
> +	R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
> +	R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
> +	R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
> +	R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
> +	R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
> +	R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
> +	R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
> +	R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
> +	R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
> +	R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
> +	R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
> +	R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
> +	R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
> +	R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
> +	R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
> +	R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
> +	R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
> +	R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
> +
> +	/* Add the working vars back into context.state[] */
> +	state[0] += a;
> +	state[1] += b;
> +	state[2] += c;
> +	state[3] += d;
> +	state[4] += e;
> +
> +	/* Wipe variables */
> +	a = b = c = d = e = 0;
> +}
> +
> +
> +/*
> + * SHA1Init - Initialize new context
> + */
> +void
> +SHA1Init(SHA1_CTX *context)
> +{
> +
> +	/* SHA1 initialization constants */
> +	context->count = 0;
> +	context->state[0] = 0x67452301;
> +	context->state[1] = 0xEFCDAB89;
> +	context->state[2] = 0x98BADCFE;
> +	context->state[3] = 0x10325476;
> +	context->state[4] = 0xC3D2E1F0;
> +}
> +
> +
> +/*
> + * Run your data through this.
> + */
> +void
> +SHA1Update(SHA1_CTX *context, const uint8_t *data, size_t len)
> +{
> +	size_t i, j;
> +
> +	j = (size_t)((context->count >> 3) & 63);
> +	context->count += (len << 3);
> +	if ((j + len) > 63) {
> +		(void)memcpy(&context->buffer[j], data, (i = 64-j));
> +		SHA1Transform(context->state, context->buffer);
> +		for ( ; i + 63 < len; i += 64)
> +			SHA1Transform(context->state, (uint8_t *)&data[i]);
> +		j = 0;
> +	} else {
> +		i = 0;
> +	}
> +	(void)memcpy(&context->buffer[j], &data[i], len - i);
> +}
> +
> +
> +/*
> + * Add padding and return the message digest.
> + */
> +void
> +SHA1Pad(SHA1_CTX *context)
> +{
> +	uint8_t finalcount[8];
> +	uint32_t i;
> +
> +	for (i = 0; i < 8; i++) {
> +		finalcount[i] = (uint8_t)((context->count >>
> +		    ((7 - (i & 7)) * 8)) & 255);	/* Endian independent */
> +	}
> +	SHA1Update(context, (uint8_t *)"\200", 1);
> +	while ((context->count & 504) != 448)
> +		SHA1Update(context, (uint8_t *)"\0", 1);
> +	SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
> +}
> +
> +void
> +SHA1Final(uint8_t digest[SHA1_DIGEST_LENGTH], SHA1_CTX *context)
> +{
> +	uint32_t i;
> +
> +	SHA1Pad(context);
> +	for (i = 0; i < SHA1_DIGEST_LENGTH; i++) {
> +		digest[i] = (uint8_t)
> +		   ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
> +	}
> +	memset(context, 0, sizeof(*context));
> +}
> diff --git a/src/util/sha1/sha1.h b/src/util/sha1/sha1.h
> new file mode 100644
> index 0000000000..d3d0bba21c
> --- /dev/null
> +++ b/src/util/sha1/sha1.h
> @@ -0,0 +1,47 @@
> +/*	$OpenBSD: sha1.h,v 1.24 2012/12/05 23:19:57 deraadt Exp $	*/
> +
> +/*
> + * SHA-1 in C
> + * By Steve Reid <steve at edmweb.com>
> + * 100% Public Domain
> + */
> +
> +#ifndef _SHA1_H
> +#define _SHA1_H
> +
> +#include <stddef.h>
> +#include <stdint.h>
> +
> +#define	SHA1_BLOCK_LENGTH		64
> +#define	SHA1_DIGEST_LENGTH		20
> +#define	SHA1_DIGEST_STRING_LENGTH	(SHA1_DIGEST_LENGTH * 2 + 1)
> +
> +typedef struct {
> +    uint32_t state[5];
> +    uint64_t count;
> +    uint8_t buffer[SHA1_BLOCK_LENGTH];
> +} SHA1_CTX;
> +
> +__BEGIN_DECLS
> +void SHA1Init(SHA1_CTX *);
> +void SHA1Pad(SHA1_CTX *);
> +void SHA1Transform(uint32_t [5], const uint8_t [SHA1_BLOCK_LENGTH]);
> +void SHA1Update(SHA1_CTX *, const uint8_t *, size_t);
> +void SHA1Final(uint8_t [SHA1_DIGEST_LENGTH], SHA1_CTX *);
> +__END_DECLS
> +
> +#define HTONDIGEST(x) do {                                              \
> +        x[0] = htonl(x[0]);                                             \
> +        x[1] = htonl(x[1]);                                             \
> +        x[2] = htonl(x[2]);                                             \
> +        x[3] = htonl(x[3]);                                             \
> +        x[4] = htonl(x[4]); } while (0)
> +
> +#define NTOHDIGEST(x) do {                                              \
> +        x[0] = ntohl(x[0]);                                             \
> +        x[1] = ntohl(x[1]);                                             \
> +        x[2] = ntohl(x[2]);                                             \
> +        x[3] = ntohl(x[3]);                                             \
> +        x[4] = ntohl(x[4]); } while (0)
> +
> +#endif /* _SHA1_H */
> -- 
> 2.11.0
> 


More information about the mesa-dev mailing list