[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