mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-20 21:38:26 +00:00
502 lines
14 KiB
C
502 lines
14 KiB
C
/* 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
|
|
|
|
#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
|