1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 23:48:12 +00:00
trezor-firmware/crypto/groestl_internal.h

464 lines
15 KiB
C
Raw Normal View History

/* Groestl hash from https://github.com/Groestlcoin/vanitygen
* Trezor adaptation by Yura Pakhuchiy <pakhuchiy@gmail.com>. */
2018-03-11 04:35:45 +00:00
/**
* 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
*
2018-03-11 04:35:45 +00:00
* 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:
*
2018-03-11 04:35:45 +00:00
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
2018-03-11 04:35:45 +00:00
* 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__
2018-03-11 04:35:45 +00:00
#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))
2018-03-11 04:35:45 +00:00
#else
#error We need at least C99 compiler
2018-03-11 04:35:45 +00:00
#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)))
2018-03-11 04:35:45 +00:00
#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)))
2018-03-11 04:35:45 +00:00
/*
* 32-bit x86, aka "i386 compatible".
*/
#if defined __i386__ || defined _M_IX86
#define SPH_DETECT_LITTLE_ENDIAN 1
#define SPH_DETECT_BIG_ENDIAN 0
2018-03-11 04:35:45 +00:00
/*
* 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
2018-03-11 04:35:45 +00:00
/*
* ARM, little-endian.
*/
#elif defined __arm__ && __ARMEL__
#define SPH_DETECT_LITTLE_ENDIAN 1
#define SPH_DETECT_BIG_ENDIAN 0
2018-03-11 04:35:45 +00:00
2020-12-16 23:07:41 +00:00
/*
* ARM64, little-endian.
*/
#elif defined __aarch64__
#define SPH_DETECT_LITTLE_ENDIAN 1
#define SPH_DETECT_BIG_ENDIAN 0
2020-12-16 23:07:41 +00:00
2018-03-11 04:35:45 +00:00
#endif
#if defined SPH_DETECT_LITTLE_ENDIAN && !defined SPH_LITTLE_ENDIAN
#define SPH_LITTLE_ENDIAN SPH_DETECT_LITTLE_ENDIAN
2018-03-11 04:35:45 +00:00
#endif
#if defined SPH_DETECT_BIG_ENDIAN && !defined SPH_BIG_ENDIAN
#define SPH_BIG_ENDIAN SPH_DETECT_BIG_ENDIAN
2018-03-11 04:35:45 +00:00
#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;
2018-03-11 04:35:45 +00:00
}
/**
* 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;
2018-03-11 04:35:45 +00:00
}
static inline void sph_enc16be(void *dst, unsigned val) {
((unsigned char *)dst)[0] = (val >> 8);
((unsigned char *)dst)[1] = val;
2018-03-11 04:35:45 +00:00
}
static inline unsigned sph_dec16be(const void *src) {
return ((unsigned)(((const unsigned char *)src)[0]) << 8) |
(unsigned)(((const unsigned char *)src)[1]);
2018-03-11 04:35:45 +00:00
}
static inline void sph_enc16le(void *dst, unsigned val) {
((unsigned char *)dst)[0] = val;
((unsigned char *)dst)[1] = val >> 8;
2018-03-11 04:35:45 +00:00
}
static inline unsigned sph_dec16le(const void *src) {
return (unsigned)(((const unsigned char *)src)[0]) |
((unsigned)(((const unsigned char *)src)[1]) << 8);
2018-03-11 04:35:45 +00:00
}
/**
* 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;
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
*(sph_u32 *)dst = sph_bswap32(val);
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
*(sph_u32 *)dst = val;
2018-03-11 04:35:45 +00:00
#else
((unsigned char *)dst)[0] = (val >> 24);
((unsigned char *)dst)[1] = (val >> 16);
((unsigned char *)dst)[2] = (val >> 8);
((unsigned char *)dst)[3] = val;
2018-03-11 04:35:45 +00:00
#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]);
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
return sph_bswap32(*(const sph_u32 *)src);
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
return *(const sph_u32 *)src;
2018-03-11 04:35:45 +00:00
#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]);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
*(sph_u32 *)dst = val;
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
*(sph_u32 *)dst = sph_bswap32(val);
2018-03-11 04:35:45 +00:00
#else
((unsigned char *)dst)[0] = val;
((unsigned char *)dst)[1] = (val >> 8);
((unsigned char *)dst)[2] = (val >> 16);
((unsigned char *)dst)[3] = (val >> 24);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
return *(const sph_u32 *)src;
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
return sph_bswap32(*(const sph_u32 *)src);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
#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;
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
*(sph_u64 *)dst = sph_bswap64(val);
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
*(sph_u64 *)dst = val;
2018-03-11 04:35:45 +00:00
#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;
2018-03-11 04:35:45 +00:00
#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]);
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
return sph_bswap64(*(const sph_u64 *)src);
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
return *(const sph_u64 *)src;
2018-03-11 04:35:45 +00:00
#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]);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
*(sph_u64 *)dst = val;
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
*(sph_u64 *)dst = sph_bswap64(val);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
}
/**
* 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) {
2018-03-11 04:35:45 +00:00
#if SPH_LITTLE_ENDIAN
return *(const sph_u64 *)src;
2018-03-11 04:35:45 +00:00
#elif SPH_BIG_ENDIAN
return sph_bswap64(*(const sph_u64 *)src);
2018-03-11 04:35:45 +00:00
#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);
2018-03-11 04:35:45 +00:00
#endif
}
#endif