/* Groestl hash from https://github.com/Groestlcoin/vanitygen * Trezor adaptation by Yura Pakhuchiy <pakhuchiy@gmail.com>. */ /** * Basic type definitions. * * This header file defines the generic integer types that will be used * for the implementation of hash functions; it also contains helper * functions which encode and decode multi-byte integer values, using * either little-endian or big-endian conventions. * * This file contains a compile-time test on the size of a byte * (the <code>unsigned char</code> C type). If bytes are not octets, * i.e. if they do not have a size of exactly 8 bits, then compilation * is aborted. Architectures where bytes are not octets are relatively * rare, even in the embedded devices market. We forbid non-octet bytes * because there is no clear convention on how octet streams are encoded * on such systems. * * ==========================(LICENSE BEGIN)============================ * * Copyright (c) 2007-2010 Projet RNRT SAPHIR * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * ===========================(LICENSE END)============================= * * @file sph_types.h * @author Thomas Pornin <thomas.pornin@cryptolog.com> */ #ifndef GROESTL_INTERNAL_H__ #define GROESTL_INTERNAL_H__ #include <limits.h> /* * All our I/O functions are defined over octet streams. We do not know * how to handle input data if bytes are not octets. */ #if CHAR_BIT != 8 #error This code requires 8-bit bytes #endif #if defined __STDC__ && __STDC_VERSION__ >= 199901L #include <stdint.h> typedef uint32_t sph_u32; typedef int32_t sph_s32; typedef uint64_t sph_u64; typedef int64_t sph_s64; #define SPH_C32(x) ((sph_u32)(x)) #define SPH_C64(x) ((sph_u64)(x)) #else #error We need at least C99 compiler #endif #define SPH_T32(x) ((x) & SPH_C32(0xFFFFFFFF)) #define SPH_ROTL32(x, n) SPH_T32(((x) << (n)) | ((x) >> (32 - (n)))) #define SPH_ROTR32(x, n) SPH_ROTL32(x, (32 - (n))) #define SPH_T64(x) ((x) & SPH_C64(0xFFFFFFFFFFFFFFFF)) #define SPH_ROTL64(x, n) SPH_T64(((x) << (n)) | ((x) >> (64 - (n)))) #define SPH_ROTR64(x, n) SPH_ROTL64(x, (64 - (n))) /* * 32-bit x86, aka "i386 compatible". */ #if defined __i386__ || defined _M_IX86 #define SPH_DETECT_LITTLE_ENDIAN 1 #define SPH_DETECT_BIG_ENDIAN 0 /* * 64-bit x86, hereafter known as "amd64". */ #elif defined __x86_64 || defined _M_X64 #define SPH_DETECT_LITTLE_ENDIAN 1 #define SPH_DETECT_BIG_ENDIAN 0 /* * ARM, little-endian. */ #elif defined __arm__ && __ARMEL__ #define SPH_DETECT_LITTLE_ENDIAN 1 #define SPH_DETECT_BIG_ENDIAN 0 /* * ARM64, little-endian. */ #elif defined __aarch64__ #define SPH_DETECT_LITTLE_ENDIAN 1 #define SPH_DETECT_BIG_ENDIAN 0 #endif #if defined SPH_DETECT_LITTLE_ENDIAN && !defined SPH_LITTLE_ENDIAN #define SPH_LITTLE_ENDIAN SPH_DETECT_LITTLE_ENDIAN #endif #if defined SPH_DETECT_BIG_ENDIAN && !defined SPH_BIG_ENDIAN #define SPH_BIG_ENDIAN SPH_DETECT_BIG_ENDIAN #endif static inline sph_u32 sph_bswap32(sph_u32 x) { x = SPH_T32((x << 16) | (x >> 16)); x = ((x & SPH_C32(0xFF00FF00)) >> 8) | ((x & SPH_C32(0x00FF00FF)) << 8); return x; } /** * Byte-swap a 64-bit value. * * @param x the input value * @return the byte-swapped value */ static inline sph_u64 sph_bswap64(sph_u64 x) { x = SPH_T64((x << 32) | (x >> 32)); x = ((x & SPH_C64(0xFFFF0000FFFF0000)) >> 16) | ((x & SPH_C64(0x0000FFFF0000FFFF)) << 16); x = ((x & SPH_C64(0xFF00FF00FF00FF00)) >> 8) | ((x & SPH_C64(0x00FF00FF00FF00FF)) << 8); return x; } static inline void sph_enc16be(void *dst, unsigned val) { ((unsigned char *)dst)[0] = (val >> 8); ((unsigned char *)dst)[1] = val; } static inline unsigned sph_dec16be(const void *src) { return ((unsigned)(((const unsigned char *)src)[0]) << 8) | (unsigned)(((const unsigned char *)src)[1]); } static inline void sph_enc16le(void *dst, unsigned val) { ((unsigned char *)dst)[0] = val; ((unsigned char *)dst)[1] = val >> 8; } static inline unsigned sph_dec16le(const void *src) { return (unsigned)(((const unsigned char *)src)[0]) | ((unsigned)(((const unsigned char *)src)[1]) << 8); } /** * Encode a 32-bit value into the provided buffer (big endian convention). * * @param dst the destination buffer * @param val the 32-bit value to encode */ static inline void sph_enc32be(void *dst, sph_u32 val) { ((unsigned char *)dst)[0] = (val >> 24); ((unsigned char *)dst)[1] = (val >> 16); ((unsigned char *)dst)[2] = (val >> 8); ((unsigned char *)dst)[3] = val; } /** * Encode a 32-bit value into the provided buffer (big endian convention). * The destination buffer must be properly aligned. * * @param dst the destination buffer (32-bit aligned) * @param val the value to encode */ static inline void sph_enc32be_aligned(void *dst, sph_u32 val) { #if SPH_LITTLE_ENDIAN *(sph_u32 *)dst = sph_bswap32(val); #elif SPH_BIG_ENDIAN *(sph_u32 *)dst = val; #else ((unsigned char *)dst)[0] = (val >> 24); ((unsigned char *)dst)[1] = (val >> 16); ((unsigned char *)dst)[2] = (val >> 8); ((unsigned char *)dst)[3] = val; #endif } /** * Decode a 32-bit value from the provided buffer (big endian convention). * * @param src the source buffer * @return the decoded value */ static inline sph_u32 sph_dec32be(const void *src) { return ((sph_u32)(((const unsigned char *)src)[0]) << 24) | ((sph_u32)(((const unsigned char *)src)[1]) << 16) | ((sph_u32)(((const unsigned char *)src)[2]) << 8) | (sph_u32)(((const unsigned char *)src)[3]); } /** * Decode a 32-bit value from the provided buffer (big endian convention). * The source buffer must be properly aligned. * * @param src the source buffer (32-bit aligned) * @return the decoded value */ static inline sph_u32 sph_dec32be_aligned(const void *src) { #if SPH_LITTLE_ENDIAN return sph_bswap32(*(const sph_u32 *)src); #elif SPH_BIG_ENDIAN return *(const sph_u32 *)src; #else return ((sph_u32)(((const unsigned char *)src)[0]) << 24) | ((sph_u32)(((const unsigned char *)src)[1]) << 16) | ((sph_u32)(((const unsigned char *)src)[2]) << 8) | (sph_u32)(((const unsigned char *)src)[3]); #endif } /** * Encode a 32-bit value into the provided buffer (little endian convention). * * @param dst the destination buffer * @param val the 32-bit value to encode */ static inline void sph_enc32le(void *dst, sph_u32 val) { ((unsigned char *)dst)[0] = val; ((unsigned char *)dst)[1] = (val >> 8); ((unsigned char *)dst)[2] = (val >> 16); ((unsigned char *)dst)[3] = (val >> 24); } /** * Encode a 32-bit value into the provided buffer (little endian convention). * The destination buffer must be properly aligned. * * @param dst the destination buffer (32-bit aligned) * @param val the value to encode */ static inline void sph_enc32le_aligned(void *dst, sph_u32 val) { #if SPH_LITTLE_ENDIAN *(sph_u32 *)dst = val; #elif SPH_BIG_ENDIAN *(sph_u32 *)dst = sph_bswap32(val); #else ((unsigned char *)dst)[0] = val; ((unsigned char *)dst)[1] = (val >> 8); ((unsigned char *)dst)[2] = (val >> 16); ((unsigned char *)dst)[3] = (val >> 24); #endif } /** * Decode a 32-bit value from the provided buffer (little endian convention). * * @param src the source buffer * @return the decoded value */ static inline sph_u32 sph_dec32le(const void *src) { return (sph_u32)(((const unsigned char *)src)[0]) | ((sph_u32)(((const unsigned char *)src)[1]) << 8) | ((sph_u32)(((const unsigned char *)src)[2]) << 16) | ((sph_u32)(((const unsigned char *)src)[3]) << 24); } /** * Decode a 32-bit value from the provided buffer (little endian convention). * The source buffer must be properly aligned. * * @param src the source buffer (32-bit aligned) * @return the decoded value */ static inline sph_u32 sph_dec32le_aligned(const void *src) { #if SPH_LITTLE_ENDIAN return *(const sph_u32 *)src; #elif SPH_BIG_ENDIAN return sph_bswap32(*(const sph_u32 *)src); #else return (sph_u32)(((const unsigned char *)src)[0]) | ((sph_u32)(((const unsigned char *)src)[1]) << 8) | ((sph_u32)(((const unsigned char *)src)[2]) << 16) | ((sph_u32)(((const unsigned char *)src)[3]) << 24); #endif } /** * Encode a 64-bit value into the provided buffer (big endian convention). * * @param dst the destination buffer * @param val the 64-bit value to encode */ static inline void sph_enc64be(void *dst, sph_u64 val) { ((unsigned char *)dst)[0] = (val >> 56); ((unsigned char *)dst)[1] = (val >> 48); ((unsigned char *)dst)[2] = (val >> 40); ((unsigned char *)dst)[3] = (val >> 32); ((unsigned char *)dst)[4] = (val >> 24); ((unsigned char *)dst)[5] = (val >> 16); ((unsigned char *)dst)[6] = (val >> 8); ((unsigned char *)dst)[7] = val; } /** * Encode a 64-bit value into the provided buffer (big endian convention). * The destination buffer must be properly aligned. * * @param dst the destination buffer (64-bit aligned) * @param val the value to encode */ static inline void sph_enc64be_aligned(void *dst, sph_u64 val) { #if SPH_LITTLE_ENDIAN *(sph_u64 *)dst = sph_bswap64(val); #elif SPH_BIG_ENDIAN *(sph_u64 *)dst = val; #else ((unsigned char *)dst)[0] = (val >> 56); ((unsigned char *)dst)[1] = (val >> 48); ((unsigned char *)dst)[2] = (val >> 40); ((unsigned char *)dst)[3] = (val >> 32); ((unsigned char *)dst)[4] = (val >> 24); ((unsigned char *)dst)[5] = (val >> 16); ((unsigned char *)dst)[6] = (val >> 8); ((unsigned char *)dst)[7] = val; #endif } /** * Decode a 64-bit value from the provided buffer (big endian convention). * * @param src the source buffer * @return the decoded value */ static inline sph_u64 sph_dec64be(const void *src) { return ((sph_u64)(((const unsigned char *)src)[0]) << 56) | ((sph_u64)(((const unsigned char *)src)[1]) << 48) | ((sph_u64)(((const unsigned char *)src)[2]) << 40) | ((sph_u64)(((const unsigned char *)src)[3]) << 32) | ((sph_u64)(((const unsigned char *)src)[4]) << 24) | ((sph_u64)(((const unsigned char *)src)[5]) << 16) | ((sph_u64)(((const unsigned char *)src)[6]) << 8) | (sph_u64)(((const unsigned char *)src)[7]); } /** * Decode a 64-bit value from the provided buffer (big endian convention). * The source buffer must be properly aligned. * * @param src the source buffer (64-bit aligned) * @return the decoded value */ static inline sph_u64 sph_dec64be_aligned(const void *src) { #if SPH_LITTLE_ENDIAN return sph_bswap64(*(const sph_u64 *)src); #elif SPH_BIG_ENDIAN return *(const sph_u64 *)src; #else return ((sph_u64)(((const unsigned char *)src)[0]) << 56) | ((sph_u64)(((const unsigned char *)src)[1]) << 48) | ((sph_u64)(((const unsigned char *)src)[2]) << 40) | ((sph_u64)(((const unsigned char *)src)[3]) << 32) | ((sph_u64)(((const unsigned char *)src)[4]) << 24) | ((sph_u64)(((const unsigned char *)src)[5]) << 16) | ((sph_u64)(((const unsigned char *)src)[6]) << 8) | (sph_u64)(((const unsigned char *)src)[7]); #endif } /** * Encode a 64-bit value into the provided buffer (little endian convention). * * @param dst the destination buffer * @param val the 64-bit value to encode */ static inline void sph_enc64le(void *dst, sph_u64 val) { ((unsigned char *)dst)[0] = val; ((unsigned char *)dst)[1] = (val >> 8); ((unsigned char *)dst)[2] = (val >> 16); ((unsigned char *)dst)[3] = (val >> 24); ((unsigned char *)dst)[4] = (val >> 32); ((unsigned char *)dst)[5] = (val >> 40); ((unsigned char *)dst)[6] = (val >> 48); ((unsigned char *)dst)[7] = (val >> 56); } /** * Encode a 64-bit value into the provided buffer (little endian convention). * The destination buffer must be properly aligned. * * @param dst the destination buffer (64-bit aligned) * @param val the value to encode */ static inline void sph_enc64le_aligned(void *dst, sph_u64 val) { #if SPH_LITTLE_ENDIAN *(sph_u64 *)dst = val; #elif SPH_BIG_ENDIAN *(sph_u64 *)dst = sph_bswap64(val); #else ((unsigned char *)dst)[0] = val; ((unsigned char *)dst)[1] = (val >> 8); ((unsigned char *)dst)[2] = (val >> 16); ((unsigned char *)dst)[3] = (val >> 24); ((unsigned char *)dst)[4] = (val >> 32); ((unsigned char *)dst)[5] = (val >> 40); ((unsigned char *)dst)[6] = (val >> 48); ((unsigned char *)dst)[7] = (val >> 56); #endif } /** * Decode a 64-bit value from the provided buffer (little endian convention). * * @param src the source buffer * @return the decoded value */ static inline sph_u64 sph_dec64le(const void *src) { return (sph_u64)(((const unsigned char *)src)[0]) | ((sph_u64)(((const unsigned char *)src)[1]) << 8) | ((sph_u64)(((const unsigned char *)src)[2]) << 16) | ((sph_u64)(((const unsigned char *)src)[3]) << 24) | ((sph_u64)(((const unsigned char *)src)[4]) << 32) | ((sph_u64)(((const unsigned char *)src)[5]) << 40) | ((sph_u64)(((const unsigned char *)src)[6]) << 48) | ((sph_u64)(((const unsigned char *)src)[7]) << 56); } /** * Decode a 64-bit value from the provided buffer (little endian convention). * The source buffer must be properly aligned. * * @param src the source buffer (64-bit aligned) * @return the decoded value */ static inline sph_u64 sph_dec64le_aligned(const void *src) { #if SPH_LITTLE_ENDIAN return *(const sph_u64 *)src; #elif SPH_BIG_ENDIAN return sph_bswap64(*(const sph_u64 *)src); #else return (sph_u64)(((const unsigned char *)src)[0]) | ((sph_u64)(((const unsigned char *)src)[1]) << 8) | ((sph_u64)(((const unsigned char *)src)[2]) << 16) | ((sph_u64)(((const unsigned char *)src)[3]) << 24) | ((sph_u64)(((const unsigned char *)src)[4]) << 32) | ((sph_u64)(((const unsigned char *)src)[5]) << 40) | ((sph_u64)(((const unsigned char *)src)[6]) << 48) | ((sph_u64)(((const unsigned char *)src)[7]) << 56); #endif } #endif