util: import sha1 implementation from OpenBSD
authorEmil Velikov <emil.velikov@collabora.com>
Fri, 13 Jan 2017 16:51:31 +0000 (16:51 +0000)
committerEmil Velikov <emil.l.velikov@gmail.com>
Wed, 18 Jan 2017 19:07:23 +0000 (19:07 +0000)
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.

As an added bonus this will avoid all the 'fun' experiences trying to
integrate it with the Android and SCons builds.

v2: Manually expand __BEGIN_DECLS/__END_DECLS and document (Tapani).

Furthermore it seems that some games (or surrounding runtime) static
link against OpenSSL resulting in conflicts. For more information see
the discussion thread [3]

Bugzilla [1]: https://bugs.freedesktop.org/show_bug.cgi?id=94904
Bugzilla [2]: https://bugs.freedesktop.org/show_bug.cgi?id=97967
[3] https://lists.freedesktop.org/archives/mesa-dev/2017-January/140748.html
Cc: Mark Janes <mark.a.janes@intel.com>
Cc: Vinson Lee <vlee@freedesktop.org>
Cc: Tapani Pälli <tapani.palli@intel.com>
Cc: Jonathan Gray <jsg@jsg.id.au>
Tested-by: Jonathan Gray <jsg@jsg.id.au>
Signed-off-by: Emil Velikov <emil.velikov@collabora.com>
Acked-by: Tapani Pälli <tapani.palli@intel.com> (v1)
Acked-by: Jason Ekstrand <jason@jlekstrand.net> (v1)
12 files changed:
configure.ac
src/compiler/glsl/tests/cache_test.c
src/mesa/main/shaderapi.c
src/util/Makefile.am
src/util/Makefile.sources
src/util/SConscript
src/util/disk_cache.c
src/util/disk_cache.h
src/util/mesa-sha1.c
src/util/sha1/README [new file with mode: 0644]
src/util/sha1/sha1.c [new file with mode: 0644]
src/util/sha1/sha1.h [new file with mode: 0644]

index 33f1c42c8bed48c7d86672fd87b9e1c037b9968b..6b07b2d7d4f70794d1eceb4954846703e23e196b 100644 (file)
@@ -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"),
@@ -1437,151 +1436,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
     require_dri_shared_libs_and_glapi "DRI"
 
@@ -1895,9 +1749,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;
 
             ;;
@@ -1905,10 +1756,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])
             ;;
@@ -2972,13 +2820,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"
index 0ef05aacb265482ba65d6cbd8f09f010a8bd14ac..f53ef0de1454fa97fdb66c10ee9477d42482cf6d 100644 (file)
@@ -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;
 }
index fe4cf1bed22cf7c23b1fed3a96ba581701aa52b7..96a4ce08349d1d399c39ce0f5b1c52b0cd11fbe5 100644 (file)
@@ -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);
 
index 093589163bae0573a983f90fe19df00d87a863cb..32316b038f263b5437f5a6020cb24a309e7a0d48 100644 (file)
@@ -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
index d2ae5e734dc41fc7037c7dfe8690bd47fcbf8eba..a68a5fe22fa7484803d2186c4e2bb171e129c97f 100644 (file)
@@ -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 \
index 73f34303976a0943455bdc49e10c97b4d84e1e4a..7e447f6e038b8d73d16671ee178026a1f67acf30 100644 (file)
@@ -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,
index 80dc7881d591cbef46b1a39fe782f2f447b0e8a2..76bdfe8e8b629abc62b6bd45c5ba9220c6a71566 100644 (file)
@@ -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
index 7e9cb809b597738b7a5d07e25768589371e9c59c..0b20665e970d2da92074d029dc31ce66bf1efa6b 100644 (file)
@@ -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
index b6a192f4dab663e12132ea8fe03058f3874a8cda..e8f1bad22f08c78882818e69463b2c278257b633 100644 (file)
  * 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 (file)
index 0000000..f13baf9
--- /dev/null
@@ -0,0 +1,59 @@
+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 ?)
+
+ - Manually expand __BEGIN_DECLS/__END_DECLS and make sure that they include
+the struct declaration.
+Upstream status: TBD
diff --git a/src/util/sha1/sha1.c b/src/util/sha1/sha1.c
new file mode 100644 (file)
index 0000000..ef59ea1
--- /dev/null
@@ -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@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 (file)
index 0000000..de07e1a
--- /dev/null
@@ -0,0 +1,54 @@
+/*     $OpenBSD: sha1.h,v 1.24 2012/12/05 23:19:57 deraadt Exp $       */
+
+/*
+ * SHA-1 in C
+ * By Steve Reid <steve@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)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    uint32_t state[5];
+    uint64_t count;
+    uint8_t buffer[SHA1_BLOCK_LENGTH];
+} SHA1_CTX;
+
+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)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SHA1_H */