summaryrefslogtreecommitdiff
path: root/src/crypto_endian.h
diff options
context:
space:
mode:
authorNils Maier <maierman@web.de>2014-06-10 13:09:08 +0200
committerNils Maier <maierman@web.de>2014-06-24 20:45:05 +0200
commit85876699954e64e2a19b137d71d9434caa9d6514 (patch)
treeff0381e32161e30cfeee850226f325125fc2d50f /src/crypto_endian.h
parent60032bf0abc7a8cbb83e649d5cb5cebe803f7f94 (diff)
Fix big endianess support in InternalMessageDigest and PBKDF2
- Replace sha1/md5 implementation by ones from https://github.com/nmaier/crypto - Add endianess functionality fro https://github.com/nmaier/crypto Closes GH-239
Diffstat (limited to 'src/crypto_endian.h')
-rw-r--r--src/crypto_endian.h116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/crypto_endian.h b/src/crypto_endian.h
new file mode 100644
index 00000000..8284e0dd
--- /dev/null
+++ b/src/crypto_endian.h
@@ -0,0 +1,116 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+// Written in 2014 by Nils Maier
+
+#ifndef CRYPTO_ENDIAN_H
+#define CRYPTO_ENDIAN_H
+
+#include <cstdint>
+
+#include "config.h"
+
+namespace crypto {
+
+#if defined(__GNUG__)
+#define forceinline __attribute__((always_inline)) inline
+#elif defined(_MSC_VER)
+#define forceinline __forceinline
+#else // ! _MSC_VER
+#define forceinline inline
+#endif // ! _MSC_VER
+
+/* In order for this implementation to work your system (or you yourself) must
+ * define after including <sys/param.h>
+ * - LITTLE_ENDIAN
+ * - BIG_ENDIAN
+ * - BYTE_ORDER
+ * - where BYTE_ORDER == LITTLE_ENDIAN or BYTE_ORDER == BIG_ENDIAN
+ * Failing to conform will render this implementation utterly incorrect.
+ */
+#if defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
+// Itanium is dead!
+#define LITTLE_ENDIAN 1234
+#define BIG_ENDIAN 4321
+#define BYTE_ORDER LITTLE_ENDIAN
+#else // ! defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif // HAVE_SYS_PARAM_H
+#endif // ! defined(_WIN32) || defined(__INTEL_COMPILER) || defined (_MSC_VER)
+
+#if !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN) || !defined(BYTE_ORDER) || (LITTLE_ENDIAN != BYTE_ORDER && BIG_ENDIAN != BYTE_ORDER)
+#error Unsupported byte order/endianess
+#endif
+
+// Lets spend some quality time mucking around with byte swap and endian-ness.
+// First bswap32:
+#if (defined(__i386__) || defined(__x86_64__)) && defined(__GNUG__)
+#define __crypto_bswap32(p) \
+ ({ \
+ uint32_t t = p; \
+ __asm__ __volatile__("bswap %0" : "=r"(t) : "0"(t)); \
+ t; \
+ })
+#elif defined(__GNUG__)
+#define __crypto_bswap32 __builtin_bswap32
+#else // defined(__GNUG__)
+forceinline uint32_t __crypto_bswap32(uint32_t n)
+{
+ n = ((n << 8) & 0xff00ff00) | ((n >> 8) & 0xff00ff);
+ return (n << 16) | (n >> 16);
+}
+#endif // defined(__GNUG__)
+
+// Next up: bswap64
+#if defined(__x86_64__) && defined(__GNUG__)
+#define __crypto_bswap64(p) \
+ ({ \
+ uint64_t t = p; \
+ __asm__ __volatile__("bswapq %q0" : "=r"(t) : "0"(t)); \
+ t; \
+ })
+
+#elif defined(__GNUG__)
+#define __crypto_bswap64 __builtin_bswap64
+#else // defined(__GNUG__)
+forceinline uint64_t __crypto_bswap64(uint64_t n)
+{
+ n = ((n << 8) & 0xff00ff00ff00ff00) | ((n >> 8) & 0x00ff00ff00ff00ff);
+ n = ((n << 16) & 0xffff0000ffff0000) | ((n >> 16) & 0x0000ffff0000ffff);
+ return (n << 32) | (n >> 32);
+}
+#endif // defined(__GNUG__)
+
+// Time for an implementation that makes reuse easier.
+namespace {
+template<typename T>
+inline T __crypto_bswap(T n)
+{
+ static_assert(sizeof(T) != sizeof(T), "Not implemented");
+}
+
+template<>
+inline uint32_t __crypto_bswap(uint32_t n)
+{
+ return __crypto_bswap32(n);
+}
+
+template<>
+inline uint64_t __crypto_bswap(uint64_t n)
+{
+ return __crypto_bswap64(n);
+}
+} // namespace
+
+// __crypto_le and __crypto_be depending on byte order
+#if LITTLE_ENDIAN == BYTE_ORDER
+#define __crypto_be(n) __crypto_bswap(n)
+#define __crypto_le(n) (n)
+#else // LITTLE_ENDIAN == WORD_ORDER
+#define __crypto_be(n) (n)
+#define __crypto_le(n) __crypto_bswap(n)
+#endif
+
+} // namespace crypto
+
+#endif // CRYPTO_ENDIAN_H