diff options
| author | Nils Maier <maierman@web.de> | 2014-06-10 13:09:08 +0200 |
|---|---|---|
| committer | Nils Maier <maierman@web.de> | 2014-06-24 20:45:05 +0200 |
| commit | 85876699954e64e2a19b137d71d9434caa9d6514 (patch) | |
| tree | ff0381e32161e30cfeee850226f325125fc2d50f /src/crypto_endian.h | |
| parent | 60032bf0abc7a8cbb83e649d5cb5cebe803f7f94 (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.h | 116 |
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 |
