diff --git a/stratum/algos/blake2b.c b/stratum/algos/blake2b.c new file mode 100644 index 000000000..e65d2d1e4 --- /dev/null +++ b/stratum/algos/blake2b.c @@ -0,0 +1,23 @@ +/** + * Blake2-B Implementation + * tpruvot@github 2016-2018 + */ + +#include +#include + +#include +#include + +void blake2b_hash(const char* input, char* output, uint32_t len) +{ + uint32_t ALIGN(64) hash[8]; + blake2b_ctx ctx; + + blake2b_init(&ctx, 32, NULL, 0); + blake2b_update(&ctx, input, len); + blake2b_final(&ctx, hash); + + memcpy(output, hash, 32); +} + diff --git a/stratum/algos/blake2b.h b/stratum/algos/blake2b.h new file mode 100644 index 000000000..eeda45c91 --- /dev/null +++ b/stratum/algos/blake2b.h @@ -0,0 +1,16 @@ +#ifndef BLAKE2B_H +#define BLAKE2B_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void blake2b_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/dedal.c b/stratum/algos/dedal.c new file mode 100644 index 000000000..50c4f1c24 --- /dev/null +++ b/stratum/algos/dedal.c @@ -0,0 +1,187 @@ +#include +#include +#include + +#include "dedal.h" +#include "sph_blake.h" +#include "sph_bmw.h" +#include "sph_groestl.h" +#include "sph_jh.h" +#include "sph_keccak.h" +#include "sph_skein.h" +#include "sph_luffa.h" +#include "sph_cubehash.h" +#include "sph_shavite.h" +#include "sph_simd.h" +#include "sph_echo.h" +#include "sph_hamsi.h" +#include "sph_fugue.h" +#include "sph_shabal.h" +#include "sph_whirlpool.h" +#include "sph_sha2.h" + +const uint8_t Kspeed[16] = { + 200, // BLAKE + 236, // BMW + 252, // SKEIN + 224, // KECCAK + 240, // SHA512 + 230, // SHABAL + 79, // WHIRLPOOL + 78, // LUFFA + 89, // CUBEHASH + 62, // SHAVITE + 59, // FUGUE + 119, // JH + 62, // HAMSI + 52, // ECHO + 22, // SIMD + 47 // GROESTL +}; + +static void get_hash_order(const uint32_t* prevblock, uint8_t* output, uint8_t* hashrounds) +{ + uint8_t* ord = output; + uint8_t hr = 0; + uint8_t* data = (uint8_t*)prevblock; + uint16_t tspeed = 0; + + for (uint8_t i = 0; i < 6; i++) { + ord[i] = data[i] % 16; + ord[i + 6] = data[i+1] >> 4; + tspeed += Kspeed[ord[i]] + Kspeed[ord[i + 6]]; + } + hr = tspeed + 920 >> 7; + + uint8_t c = hr - 12; + for (uint8_t i = 0; i < c ; i++) { + if (i < 15) { + uint8_t j = i >> 1; + ord[i + 12] = (i & 1) ? data[j] % 6 : data[j] % 5; + } else { + ord[i + 12] = data[i - 15] % 4; + } + } + *hashrounds = hr; +} + +void dedal_hash(const char* input, char* output, uint32_t len) +{ + + unsigned char hash[128]; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_skein512_context ctx_skein; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + + const void *in = input; + int size = len; + uint32_t *in32 = (uint32_t*) input; + uint8_t hashorder[32] = {}; + uint8_t hashrounds = 0; + + get_hash_order(&in32[1], hashorder, &hashrounds); + + for (int i = 0; i < hashrounds; i++) + { + switch (hashorder[i]) + { + case 0: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case 1: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case 2: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case 3: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, in, size); + sph_keccak512_close(&ctx_keccak, hash); + break; + case 4: + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512, in, size); + sph_sha512_close(&ctx_sha512, hash); + break; + case 5: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case 6: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case 7: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, in, size); + sph_luffa512_close(&ctx_luffa, hash); + break; + case 8: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case 9: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case 10: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case 11: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case 12: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case 13: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case 14: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case 15: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + } + in = (void*)hash; + size = 64; + } + memcpy(output, hash, 32); +} diff --git a/stratum/algos/dedal.h b/stratum/algos/dedal.h new file mode 100644 index 000000000..2a84e71fa --- /dev/null +++ b/stratum/algos/dedal.h @@ -0,0 +1,16 @@ +#ifndef DEDALHASH_H +#define DEDALHASH_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void dedal_hash(const char* data, char* out, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif // DEDALHASH_H diff --git a/stratum/algos/makefile b/stratum/algos/makefile index 0af7dbb31..ca9414b8d 100644 --- a/stratum/algos/makefile +++ b/stratum/algos/makefile @@ -10,12 +10,12 @@ LDFLAGS=-O2 -lgmp SOURCES=lyra2re.c lyra2v2.c Lyra2.c lyra2z.c Lyra2-z.c Sponge.c allium.c \ c11.c x11.c x12.c x13.c hsr14.c sm3.c x14.c x15.c x17.c \ - x21s.c x22i.c SWIFFTX/SWIFFTX.c \ - blake.c blakecoin.c blake2s.c jha.c keccak.c lbry.c tribus.c exosis.c \ + x20r.c dedal.c x21s.c x22i.c SWIFFTX/SWIFFTX.c \ + blake.c blakecoin.c blake2b.c blake2s.c jha.c keccak.c lbry.c tribus.c exosis.c \ deep.c fresh.c groestl.c neoscrypt.c nist5.c quark.c qubit.c skein.c skein2.c \ bitcore.c timetravel.c x11evo.c x16r.c x16s.c xevan.c bastion.c hmq17.c sonoa.c \ bmw.c luffa.c pentablake.c vitalium.c whirlpool.c whirlpoolx.c zr5.c \ - scrypt.c scryptn.c sha256.c sha256t.c \ + scrypt.c scryptn.c sha256.c sha256t.c sha256q.c \ yescrypt.c yescrypt-opt.c sha256_Y.c \ a5a.c a5amath.c m7m.c magimath.cpp velvet.c \ argon2a.c blake2/blake2b.c ar2/argon2.c ar2/core.c ar2/encoding.c ar2/opt.c ar2/thread.c ar2/ar2-scrypt-jane.c \ @@ -43,4 +43,4 @@ clean: rm -f *.o rm -f ar2/*.o rm -f blake2/*.o - rm -f SWIFFTX/*.o + rm -f SWIFFTX/*.o \ No newline at end of file diff --git a/stratum/algos/prevector.h b/stratum/algos/prevector.h new file mode 100644 index 000000000..1d77aec7a --- /dev/null +++ b/stratum/algos/prevector.h @@ -0,0 +1,518 @@ +// Copyright (c) 2015-2016 The Bitcoin Core developers +// Copyright (c) 2017 The Astral Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef RAVEN_PREVECTOR_H +#define RAVEN_PREVECTOR_H + +#include +#include +#include +#include + +#include +#include + +#pragma pack(push, 1) +/** Implements a drop-in replacement for std::vector which stores up to N + * elements directly (without heap allocation). The types Size and Diff are + * used to store element counts, and can be any unsigned + signed type. + * + * Storage layout is either: + * - Direct allocation: + * - Size _size: the number of used elements (between 0 and N) + * - T direct[N]: an array of N elements of type T + * (only the first _size are initialized). + * - Indirect allocation: + * - Size _size: the number of used elements plus N + 1 + * - Size capacity: the number of allocated elements + * - T* indirect: a pointer to an array of capacity elements of type T + * (only the first _size are initialized). + * + * The data type T must be movable by memmove/realloc(). Once we switch to C++, + * move constructors can be used instead. + */ +template +class prevector { +public: + typedef Size size_type; + typedef Diff difference_type; + typedef T value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + + class iterator { + T* ptr; + public: + typedef Diff difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef std::random_access_iterator_tag iterator_category; + iterator(T* ptr_) : ptr(ptr_) {} + T& operator*() const { return *ptr; } + T* operator->() const { return ptr; } + T& operator[](size_type pos) { return ptr[pos]; } + const T& operator[](size_type pos) const { return ptr[pos]; } + iterator& operator++() { ptr++; return *this; } + iterator& operator--() { ptr--; return *this; } + iterator operator++(int) { iterator copy(*this); ++(*this); return copy; } + iterator operator--(int) { iterator copy(*this); --(*this); return copy; } + difference_type friend operator-(iterator a, iterator b) { return (&(*a) - &(*b)); } + iterator operator+(size_type n) { return iterator(ptr + n); } + iterator& operator+=(size_type n) { ptr += n; return *this; } + iterator operator-(size_type n) { return iterator(ptr - n); } + iterator& operator-=(size_type n) { ptr -= n; return *this; } + bool operator==(iterator x) const { return ptr == x.ptr; } + bool operator!=(iterator x) const { return ptr != x.ptr; } + bool operator>=(iterator x) const { return ptr >= x.ptr; } + bool operator<=(iterator x) const { return ptr <= x.ptr; } + bool operator>(iterator x) const { return ptr > x.ptr; } + bool operator<(iterator x) const { return ptr < x.ptr; } + }; + + class reverse_iterator { + T* ptr; + public: + typedef Diff difference_type; + typedef T value_type; + typedef T* pointer; + typedef T& reference; + typedef std::bidirectional_iterator_tag iterator_category; + reverse_iterator(T* ptr_) : ptr(ptr_) {} + T& operator*() { return *ptr; } + const T& operator*() const { return *ptr; } + T* operator->() { return ptr; } + const T* operator->() const { return ptr; } + reverse_iterator& operator--() { ptr++; return *this; } + reverse_iterator& operator++() { ptr--; return *this; } + reverse_iterator operator++(int) { reverse_iterator copy(*this); ++(*this); return copy; } + reverse_iterator operator--(int) { reverse_iterator copy(*this); --(*this); return copy; } + bool operator==(reverse_iterator x) const { return ptr == x.ptr; } + bool operator!=(reverse_iterator x) const { return ptr != x.ptr; } + }; + + class const_iterator { + const T* ptr; + public: + typedef Diff difference_type; + typedef const T value_type; + typedef const T* pointer; + typedef const T& reference; + typedef std::random_access_iterator_tag iterator_category; + const_iterator(const T* ptr_) : ptr(ptr_) {} + const_iterator(iterator x) : ptr(&(*x)) {} + const T& operator*() const { return *ptr; } + const T* operator->() const { return ptr; } + const T& operator[](size_type pos) const { return ptr[pos]; } + const_iterator& operator++() { ptr++; return *this; } + const_iterator& operator--() { ptr--; return *this; } + const_iterator operator++(int) { const_iterator copy(*this); ++(*this); return copy; } + const_iterator operator--(int) { const_iterator copy(*this); --(*this); return copy; } + difference_type friend operator-(const_iterator a, const_iterator b) { return (&(*a) - &(*b)); } + const_iterator operator+(size_type n) { return const_iterator(ptr + n); } + const_iterator& operator+=(size_type n) { ptr += n; return *this; } + const_iterator operator-(size_type n) { return const_iterator(ptr - n); } + const_iterator& operator-=(size_type n) { ptr -= n; return *this; } + bool operator==(const_iterator x) const { return ptr == x.ptr; } + bool operator!=(const_iterator x) const { return ptr != x.ptr; } + bool operator>=(const_iterator x) const { return ptr >= x.ptr; } + bool operator<=(const_iterator x) const { return ptr <= x.ptr; } + bool operator>(const_iterator x) const { return ptr > x.ptr; } + bool operator<(const_iterator x) const { return ptr < x.ptr; } + }; + + class const_reverse_iterator { + const T* ptr; + public: + typedef Diff difference_type; + typedef const T value_type; + typedef const T* pointer; + typedef const T& reference; + typedef std::bidirectional_iterator_tag iterator_category; + const_reverse_iterator(const T* ptr_) : ptr(ptr_) {} + const_reverse_iterator(reverse_iterator x) : ptr(&(*x)) {} + const T& operator*() const { return *ptr; } + const T* operator->() const { return ptr; } + const_reverse_iterator& operator--() { ptr++; return *this; } + const_reverse_iterator& operator++() { ptr--; return *this; } + const_reverse_iterator operator++(int) { const_reverse_iterator copy(*this); ++(*this); return copy; } + const_reverse_iterator operator--(int) { const_reverse_iterator copy(*this); --(*this); return copy; } + bool operator==(const_reverse_iterator x) const { return ptr == x.ptr; } + bool operator!=(const_reverse_iterator x) const { return ptr != x.ptr; } + }; + +private: + size_type _size; + union direct_or_indirect { + char direct[sizeof(T) * N]; + struct { + size_type capacity; + char* indirect; + }; + } _union; + + T* direct_ptr(difference_type pos) { return reinterpret_cast(_union.direct) + pos; } + const T* direct_ptr(difference_type pos) const { return reinterpret_cast(_union.direct) + pos; } + T* indirect_ptr(difference_type pos) { return reinterpret_cast(_union.indirect) + pos; } + const T* indirect_ptr(difference_type pos) const { return reinterpret_cast(_union.indirect) + pos; } + bool is_direct() const { return _size <= N; } + + void change_capacity(size_type new_capacity) { + if (new_capacity <= N) { + if (!is_direct()) { + T* indirect = indirect_ptr(0); + T* src = indirect; + T* dst = direct_ptr(0); + memcpy(dst, src, size() * sizeof(T)); + free(indirect); + _size -= N + 1; + } + } else { + if (!is_direct()) { + /* FIXME: Because malloc/realloc here won't call new_handler if allocation fails, assert + success. These should instead use an allocator or new/delete so that handlers + are called as necessary, but performance would be slightly degraded by doing so. */ + _union.indirect = static_cast(realloc(_union.indirect, ((size_t)sizeof(T)) * new_capacity)); + assert(_union.indirect); + _union.capacity = new_capacity; + } else { + char* new_indirect = static_cast(malloc(((size_t)sizeof(T)) * new_capacity)); + assert(new_indirect); + T* src = direct_ptr(0); + T* dst = reinterpret_cast(new_indirect); + memcpy(dst, src, size() * sizeof(T)); + _union.indirect = new_indirect; + _union.capacity = new_capacity; + _size += N + 1; + } + } + } + + T* item_ptr(difference_type pos) { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); } + const T* item_ptr(difference_type pos) const { return is_direct() ? direct_ptr(pos) : indirect_ptr(pos); } + +public: + void assign(size_type n, const T& val) { + clear(); + if (capacity() < n) { + change_capacity(n); + } + while (size() < n) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(val); + } + } + + template + void assign(InputIterator first, InputIterator last) { + size_type n = last - first; + clear(); + if (capacity() < n) { + change_capacity(n); + } + while (first != last) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(*first); + ++first; + } + } + + prevector() : _size(0), _union{{}} {} + + explicit prevector(size_type n) : _size(0) { + resize(n); + } + + explicit prevector(size_type n, const T& val = T()) : _size(0) { + change_capacity(n); + while (size() < n) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(val); + } + } + + template + prevector(InputIterator first, InputIterator last) : _size(0) { + size_type n = last - first; + change_capacity(n); + while (first != last) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(*first); + ++first; + } + } + + prevector(const prevector& other) : _size(0) { + change_capacity(other.size()); + const_iterator it = other.begin(); + while (it != other.end()) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(*it); + ++it; + } + } + + prevector(prevector&& other) : _size(0) { + swap(other); + } + + prevector& operator=(const prevector& other) { + if (&other == this) { + return *this; + } + resize(0); + change_capacity(other.size()); + const_iterator it = other.begin(); + while (it != other.end()) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(*it); + ++it; + } + return *this; + } + + prevector& operator=(prevector&& other) { + swap(other); + return *this; + } + + size_type size() const { + return is_direct() ? _size : _size - N - 1; + } + + bool empty() const { + return size() == 0; + } + + iterator begin() { return iterator(item_ptr(0)); } + const_iterator begin() const { return const_iterator(item_ptr(0)); } + iterator end() { return iterator(item_ptr(size())); } + const_iterator end() const { return const_iterator(item_ptr(size())); } + + reverse_iterator rbegin() { return reverse_iterator(item_ptr(size() - 1)); } + const_reverse_iterator rbegin() const { return const_reverse_iterator(item_ptr(size() - 1)); } + reverse_iterator rend() { return reverse_iterator(item_ptr(-1)); } + const_reverse_iterator rend() const { return const_reverse_iterator(item_ptr(-1)); } + + size_t capacity() const { + if (is_direct()) { + return N; + } else { + return _union.capacity; + } + } + + T& operator[](size_type pos) { + return *item_ptr(pos); + } + + const T& operator[](size_type pos) const { + return *item_ptr(pos); + } + + void resize(size_type new_size) { + if (size() > new_size) { + erase(item_ptr(new_size), end()); + } + if (new_size > capacity()) { + change_capacity(new_size); + } + while (size() < new_size) { + _size++; + new(static_cast(item_ptr(size() - 1))) T(); + } + } + + void reserve(size_type new_capacity) { + if (new_capacity > capacity()) { + change_capacity(new_capacity); + } + } + + void shrink_to_fit() { + change_capacity(size()); + } + + void clear() { + resize(0); + } + + iterator insert(iterator pos, const T& value) { + size_type p = pos - begin(); + size_type new_size = size() + 1; + if (capacity() < new_size) { + change_capacity(new_size + (new_size >> 1)); + } + memmove(item_ptr(p + 1), item_ptr(p), (size() - p) * sizeof(T)); + _size++; + new(static_cast(item_ptr(p))) T(value); + return iterator(item_ptr(p)); + } + + void insert(iterator pos, size_type count, const T& value) { + size_type p = pos - begin(); + size_type new_size = size() + count; + if (capacity() < new_size) { + change_capacity(new_size + (new_size >> 1)); + } + memmove(item_ptr(p + count), item_ptr(p), (size() - p) * sizeof(T)); + _size += count; + for (size_type i = 0; i < count; i++) { + new(static_cast(item_ptr(p + i))) T(value); + } + } + + template + void insert(iterator pos, InputIterator first, InputIterator last) { + size_type p = pos - begin(); + difference_type count = last - first; + size_type new_size = size() + count; + if (capacity() < new_size) { + change_capacity(new_size + (new_size >> 1)); + } + memmove(item_ptr(p + count), item_ptr(p), (size() - p) * sizeof(T)); + _size += count; + while (first != last) { + new(static_cast(item_ptr(p))) T(*first); + ++p; + ++first; + } + } + + iterator erase(iterator pos) { + return erase(pos, pos + 1); + } + + iterator erase(iterator first, iterator last) { + // Erase is not allowed to the change the object's capacity. That means + // that when starting with an indirectly allocated prevector with + // size and capacity > N, the result may be a still indirectly allocated + // prevector with size <= N and capacity > N. A shrink_to_fit() call is + // necessary to switch to the (more efficient) directly allocated + // representation (with capacity N and size <= N). + iterator p = first; + char* endp = (char*)&(*end()); + if (!std::is_trivially_destructible::value) { + while (p != last) { + (*p).~T(); + _size--; + ++p; + } + } else { + _size -= last - p; + } + memmove(&(*first), &(*last), endp - ((char*)(&(*last)))); + return first; + } + + void push_back(const T& value) { + size_type new_size = size() + 1; + if (capacity() < new_size) { + change_capacity(new_size + (new_size >> 1)); + } + new(item_ptr(size())) T(value); + _size++; + } + + void pop_back() { + erase(end() - 1, end()); + } + + T& front() { + return *item_ptr(0); + } + + const T& front() const { + return *item_ptr(0); + } + + T& back() { + return *item_ptr(size() - 1); + } + + const T& back() const { + return *item_ptr(size() - 1); + } + + void swap(prevector& other) { + std::swap(_union, other._union); + std::swap(_size, other._size); + } + + ~prevector() { + if (!std::is_trivially_destructible::value) { + clear(); + } + if (!is_direct()) { + free(_union.indirect); + _union.indirect = nullptr; + } + } + + bool operator==(const prevector& other) const { + if (other.size() != size()) { + return false; + } + const_iterator b1 = begin(); + const_iterator b2 = other.begin(); + const_iterator e1 = end(); + while (b1 != e1) { + if ((*b1) != (*b2)) { + return false; + } + ++b1; + ++b2; + } + return true; + } + + bool operator!=(const prevector& other) const { + return !(*this == other); + } + + bool operator<(const prevector& other) const { + if (size() < other.size()) { + return true; + } + if (size() > other.size()) { + return false; + } + const_iterator b1 = begin(); + const_iterator b2 = other.begin(); + const_iterator e1 = end(); + while (b1 != e1) { + if ((*b1) < (*b2)) { + return true; + } + if ((*b2) < (*b1)) { + return false; + } + ++b1; + ++b2; + } + return false; + } + + size_t allocated_memory() const { + if (is_direct()) { + return 0; + } else { + return ((size_t)(sizeof(T))) * _union.capacity; + } + } + + value_type* data() { + return item_ptr(0); + } + + const value_type* data() const { + return item_ptr(0); + } +}; +#pragma pack(pop) + +#endif // RAVEN_PREVECTOR_H diff --git a/stratum/algos/serialize.h b/stratum/algos/serialize.h new file mode 100644 index 000000000..b4af9f4ce --- /dev/null +++ b/stratum/algos/serialize.h @@ -0,0 +1,978 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2016 The Bitcoin Core developers +// Copyright (c) 2017 The Astral Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef RAVEN_SERIALIZE_H +#define RAVEN_SERIALIZE_H + +#include "compat/endian.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "prevector.h" + +static const unsigned int MAX_SIZE = 0x02000000; + +/** + * Dummy data type to identify deserializing constructors. + * + * By convention, a constructor of a type T with signature + * + * template T::T(deserialize_type, Stream& s) + * + * is a deserializing constructor, which builds the type by + * deserializing it from s. If T contains const fields, this + * is likely the only way to do so. + */ +struct deserialize_type {}; +constexpr deserialize_type deserialize {}; + +/** + * Used to bypass the rule against non-const reference to temporary + * where it makes sense with wrappers such as CFlatData or CTxDB + */ +template +inline T& REF(const T& val) +{ + return const_cast(val); +} + +/** + * Used to acquire a non-const pointer "this" to generate bodies + * of const serialization operations from a template + */ +template +inline T* NCONST_PTR(const T* val) +{ + return const_cast(val); +} + +/* + * Lowest-level serialization and conversion. + * @note Sizes of these types are verified in the tests + */ +template inline void ser_writedata8(Stream &s, uint8_t obj) +{ + s.write((char*)&obj, 1); +} +template inline void ser_writedata16(Stream &s, uint16_t obj) +{ + obj = htole16(obj); + s.write((char*)&obj, 2); +} +template inline void ser_writedata32(Stream &s, uint32_t obj) +{ + obj = htole32(obj); + s.write((char*)&obj, 4); +} +template inline void ser_writedata32be(Stream &s, uint32_t obj) +{ + obj = htobe32(obj); + s.write((char*)&obj, 4); +} +template inline void ser_writedata64(Stream &s, uint64_t obj) +{ + obj = htole64(obj); + s.write((char*)&obj, 8); +} +template inline uint8_t ser_readdata8(Stream &s) +{ + uint8_t obj; + s.read((char*)&obj, 1); + return obj; +} +template inline uint16_t ser_readdata16(Stream &s) +{ + uint16_t obj; + s.read((char*)&obj, 2); + return le16toh(obj); +} +template inline uint32_t ser_readdata32(Stream &s) +{ + uint32_t obj; + s.read((char*)&obj, 4); + return le32toh(obj); +} +template inline uint32_t ser_readdata32be(Stream &s) +{ + uint32_t obj; + s.read((char*)&obj, 4); + return be32toh(obj); +} +template inline uint64_t ser_readdata64(Stream &s) +{ + uint64_t obj; + s.read((char*)&obj, 8); + return le64toh(obj); +} +inline uint64_t ser_double_to_uint64(double x) +{ + union { double x; uint64_t y; } tmp; + tmp.x = x; + return tmp.y; +} +inline uint32_t ser_float_to_uint32(float x) +{ + union { float x; uint32_t y; } tmp; + tmp.x = x; + return tmp.y; +} +inline double ser_uint64_to_double(uint64_t y) +{ + union { double x; uint64_t y; } tmp; + tmp.y = y; + return tmp.x; +} +inline float ser_uint32_to_float(uint32_t y) +{ + union { float x; uint32_t y; } tmp; + tmp.y = y; + return tmp.x; +} + + +///////////////////////////////////////////////////////////////// +// +// Templates for serializing to anything that looks like a stream, +// i.e. anything that supports .read(char*, size_t) and .write(char*, size_t) +// + +class CSizeComputer; + +enum +{ + // primary actions + SER_NETWORK = (1 << 0), + SER_DISK = (1 << 1), + SER_GETHASH = (1 << 2), +}; + +#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action)) +#define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__)) + +/** + * Implement three methods for serializable objects. These are actually wrappers over + * "SerializationOp" template, which implements the body of each class' serialization + * code. Adding "ADD_SERIALIZE_METHODS" in the body of the class causes these wrappers to be + * added as members. + */ +#define ADD_SERIALIZE_METHODS \ + template \ + void Serialize(Stream& s) const { \ + NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \ + } \ + template \ + void Unserialize(Stream& s) { \ + SerializationOp(s, CSerActionUnserialize()); \ + } + +template inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char +template inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); } +template inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); } +template inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); } +template inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); } +template inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); } +template inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); } +template inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); } +template inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); } +template inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); } +template inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); } + +template inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char +template inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); } +template inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); } +template inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); } +template inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); } +template inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); } +template inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); } +template inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); } +template inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); } +template inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); } +template inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); } + +template inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); } +template inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; } + + + + + + +/** + * Compact Size + * size < 253 -- 1 byte + * size <= USHRT_MAX -- 3 bytes (253 + 2 bytes) + * size <= UINT_MAX -- 5 bytes (254 + 4 bytes) + * size > UINT_MAX -- 9 bytes (255 + 8 bytes) + */ +inline unsigned int GetSizeOfCompactSize(uint64_t nSize) +{ + if (nSize < 253) return sizeof(unsigned char); + else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned short); + else if (nSize <= std::numeric_limits::max()) return sizeof(unsigned char) + sizeof(unsigned int); + else return sizeof(unsigned char) + sizeof(uint64_t); +} + +inline void WriteCompactSize(CSizeComputer& os, uint64_t nSize); + +template +void WriteCompactSize(Stream& os, uint64_t nSize) +{ + if (nSize < 253) + { + ser_writedata8(os, nSize); + } + else if (nSize <= std::numeric_limits::max()) + { + ser_writedata8(os, 253); + ser_writedata16(os, nSize); + } + else if (nSize <= std::numeric_limits::max()) + { + ser_writedata8(os, 254); + ser_writedata32(os, nSize); + } + else + { + ser_writedata8(os, 255); + ser_writedata64(os, nSize); + } + return; +} + +template +uint64_t ReadCompactSize(Stream& is) +{ + uint8_t chSize = ser_readdata8(is); + uint64_t nSizeRet = 0; + if (chSize < 253) + { + nSizeRet = chSize; + } + else if (chSize == 253) + { + nSizeRet = ser_readdata16(is); + if (nSizeRet < 253) + throw std::ios_base::failure("non-canonical ReadCompactSize()"); + } + else if (chSize == 254) + { + nSizeRet = ser_readdata32(is); + if (nSizeRet < 0x10000u) + throw std::ios_base::failure("non-canonical ReadCompactSize()"); + } + else + { + nSizeRet = ser_readdata64(is); + if (nSizeRet < 0x100000000ULL) + throw std::ios_base::failure("non-canonical ReadCompactSize()"); + } + if (nSizeRet > (uint64_t)MAX_SIZE) + throw std::ios_base::failure("ReadCompactSize(): size too large"); + return nSizeRet; +} + +/** + * Variable-length integers: bytes are a MSB base-128 encoding of the number. + * The high bit in each byte signifies whether another digit follows. To make + * sure the encoding is one-to-one, one is subtracted from all but the last digit. + * Thus, the byte sequence a[] with length len, where all but the last byte + * has bit 128 set, encodes the number: + * + * (a[len-1] & 0x7F) + sum(i=1..len-1, 128^i*((a[len-i-1] & 0x7F)+1)) + * + * Properties: + * * Very small (0-127: 1 byte, 128-16511: 2 bytes, 16512-2113663: 3 bytes) + * * Every integer has exactly one encoding + * * Encoding does not depend on size of original integer type + * * No redundancy: every (infinite) byte sequence corresponds to a list + * of encoded integers. + * + * 0: [0x00] 256: [0x81 0x00] + * 1: [0x01] 16383: [0xFE 0x7F] + * 127: [0x7F] 16384: [0xFF 0x00] + * 128: [0x80 0x00] 16511: [0xFF 0x7F] + * 255: [0x80 0x7F] 65535: [0x82 0xFE 0x7F] + * 2^32: [0x8E 0xFE 0xFE 0xFF 0x00] + */ + +template +inline unsigned int GetSizeOfVarInt(I n) +{ + int nRet = 0; + while(true) { + nRet++; + if (n <= 0x7F) + break; + n = (n >> 7) - 1; + } + return nRet; +} + +template +inline void WriteVarInt(CSizeComputer& os, I n); + +template +void WriteVarInt(Stream& os, I n) +{ + unsigned char tmp[(sizeof(n)*8+6)/7]; + int len=0; + while(true) { + tmp[len] = (n & 0x7F) | (len ? 0x80 : 0x00); + if (n <= 0x7F) + break; + n = (n >> 7) - 1; + len++; + } + do { + ser_writedata8(os, tmp[len]); + } while(len--); +} + +template +I ReadVarInt(Stream& is) +{ + I n = 0; + while(true) { + unsigned char chData = ser_readdata8(is); + if (n > (std::numeric_limits::max() >> 7)) { + throw std::ios_base::failure("ReadVarInt(): size too large"); + } + n = (n << 7) | (chData & 0x7F); + if (chData & 0x80) { + if (n == std::numeric_limits::max()) { + throw std::ios_base::failure("ReadVarInt(): size too large"); + } + n++; + } else { + return n; + } + } +} + +#define FLATDATA(obj) REF(CFlatData((char*)&(obj), (char*)&(obj) + sizeof(obj))) +#define VARINT(obj) REF(WrapVarInt(REF(obj))) +#define COMPACTSIZE(obj) REF(CCompactSize(REF(obj))) +#define LIMITED_STRING(obj,n) REF(LimitedString< n >(REF(obj))) + +/** + * Wrapper for serializing arrays and POD. + */ +class CFlatData +{ +protected: + char* pbegin; + char* pend; +public: + CFlatData(void* pbeginIn, void* pendIn) : pbegin((char*)pbeginIn), pend((char*)pendIn) { } + template + explicit CFlatData(std::vector &v) + { + pbegin = (char*)v.data(); + pend = (char*)(v.data() + v.size()); + } + template + explicit CFlatData(prevector &v) + { + pbegin = (char*)v.data(); + pend = (char*)(v.data() + v.size()); + } + char* begin() { return pbegin; } + const char* begin() const { return pbegin; } + char* end() { return pend; } + const char* end() const { return pend; } + + template + void Serialize(Stream& s) const + { + s.write(pbegin, pend - pbegin); + } + + template + void Unserialize(Stream& s) + { + s.read(pbegin, pend - pbegin); + } +}; + +template +class CVarInt +{ +protected: + I &n; +public: + explicit CVarInt(I& nIn) : n(nIn) { } + + template + void Serialize(Stream &s) const { + WriteVarInt(s, n); + } + + template + void Unserialize(Stream& s) { + n = ReadVarInt(s); + } +}; + +class CCompactSize +{ +protected: + uint64_t &n; +public: + explicit CCompactSize(uint64_t& nIn) : n(nIn) { } + + template + void Serialize(Stream &s) const { + WriteCompactSize(s, n); + } + + template + void Unserialize(Stream& s) { + n = ReadCompactSize(s); + } +}; + +template +class LimitedString +{ +protected: + std::string& string; +public: + explicit LimitedString(std::string& _string) : string(_string) {} + + template + void Unserialize(Stream& s) + { + size_t size = ReadCompactSize(s); + if (size > Limit) { + throw std::ios_base::failure("String length limit exceeded"); + } + string.resize(size); + if (size != 0) + s.read((char*)string.data(), size); + } + + template + void Serialize(Stream& s) const + { + WriteCompactSize(s, string.size()); + if (!string.empty()) + s.write((char*)string.data(), string.size()); + } +}; + +template +CVarInt WrapVarInt(I& n) { return CVarInt(n); } + +/** + * Forward declarations + */ + +/** + * string + */ +template void Serialize(Stream& os, const std::basic_string& str); +template void Unserialize(Stream& is, std::basic_string& str); + +/** + * prevector + * prevectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. + */ +template void Serialize_impl(Stream& os, const prevector& v, const unsigned char&); +template void Serialize_impl(Stream& os, const prevector& v, const V&); +template inline void Serialize(Stream& os, const prevector& v); +template void Unserialize_impl(Stream& is, prevector& v, const unsigned char&); +template void Unserialize_impl(Stream& is, prevector& v, const V&); +template inline void Unserialize(Stream& is, prevector& v); + +/** + * vector + * vectors of unsigned char are a special case and are intended to be serialized as a single opaque blob. + */ +template void Serialize_impl(Stream& os, const std::vector& v, const unsigned char&); +template void Serialize_impl(Stream& os, const std::vector& v, const V&); +template inline void Serialize(Stream& os, const std::vector& v); +template void Unserialize_impl(Stream& is, std::vector& v, const unsigned char&); +template void Unserialize_impl(Stream& is, std::vector& v, const V&); +template inline void Unserialize(Stream& is, std::vector& v); + +/** + * pair + */ +template void Serialize(Stream& os, const std::pair& item); +template void Unserialize(Stream& is, std::pair& item); + +/** + * map + */ +template void Serialize(Stream& os, const std::map& m); +template void Unserialize(Stream& is, std::map& m); + +/** + * set + */ +template void Serialize(Stream& os, const std::set& m); +template void Unserialize(Stream& is, std::set& m); + +/** + * shared_ptr + */ +template void Serialize(Stream& os, const std::shared_ptr& p); +template void Unserialize(Stream& os, std::shared_ptr& p); + +/** + * unique_ptr + */ +template void Serialize(Stream& os, const std::unique_ptr& p); +template void Unserialize(Stream& os, std::unique_ptr& p); + + + +/** + * If none of the specialized versions above matched, default to calling member function. + */ +template +inline void Serialize(Stream& os, const T& a) +{ + a.Serialize(os); +} + +template +inline void Unserialize(Stream& is, T& a) +{ + a.Unserialize(is); +} + + + + + +/** + * string + */ +template +void Serialize(Stream& os, const std::basic_string& str) +{ + WriteCompactSize(os, str.size()); + if (!str.empty()) + os.write((char*)str.data(), str.size() * sizeof(C)); +} + +template +void Unserialize(Stream& is, std::basic_string& str) +{ + unsigned int nSize = ReadCompactSize(is); + str.resize(nSize); + if (nSize != 0) + is.read((char*)str.data(), nSize * sizeof(C)); +} + + + +/** + * prevector + */ +template +void Serialize_impl(Stream& os, const prevector& v, const unsigned char&) +{ + WriteCompactSize(os, v.size()); + if (!v.empty()) + os.write((char*)v.data(), v.size() * sizeof(T)); +} + +template +void Serialize_impl(Stream& os, const prevector& v, const V&) +{ + WriteCompactSize(os, v.size()); + for (typename prevector::const_iterator vi = v.begin(); vi != v.end(); ++vi) + ::Serialize(os, (*vi)); +} + +template +inline void Serialize(Stream& os, const prevector& v) +{ + Serialize_impl(os, v, T()); +} + + +template +void Unserialize_impl(Stream& is, prevector& v, const unsigned char&) +{ + // Limit size per read so bogus size value won't cause out of memory + v.clear(); + unsigned int nSize = ReadCompactSize(is); + unsigned int i = 0; + while (i < nSize) + { + unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); + v.resize(i + blk); + is.read((char*)&v[i], blk * sizeof(T)); + i += blk; + } +} + +template +void Unserialize_impl(Stream& is, prevector& v, const V&) +{ + v.clear(); + unsigned int nSize = ReadCompactSize(is); + unsigned int i = 0; + unsigned int nMid = 0; + while (nMid < nSize) + { + nMid += 5000000 / sizeof(T); + if (nMid > nSize) + nMid = nSize; + v.resize(nMid); + for (; i < nMid; i++) + Unserialize(is, v[i]); + } +} + +template +inline void Unserialize(Stream& is, prevector& v) +{ + Unserialize_impl(is, v, T()); +} + + + +/** + * vector + */ +template +void Serialize_impl(Stream& os, const std::vector& v, const unsigned char&) +{ + WriteCompactSize(os, v.size()); + if (!v.empty()) + os.write((char*)v.data(), v.size() * sizeof(T)); +} + +template +void Serialize_impl(Stream& os, const std::vector& v, const V&) +{ + WriteCompactSize(os, v.size()); + for (typename std::vector::const_iterator vi = v.begin(); vi != v.end(); ++vi) + ::Serialize(os, (*vi)); +} + +template +inline void Serialize(Stream& os, const std::vector& v) +{ + Serialize_impl(os, v, T()); +} + + +template +void Unserialize_impl(Stream& is, std::vector& v, const unsigned char&) +{ + // Limit size per read so bogus size value won't cause out of memory + v.clear(); + unsigned int nSize = ReadCompactSize(is); + unsigned int i = 0; + while (i < nSize) + { + unsigned int blk = std::min(nSize - i, (unsigned int)(1 + 4999999 / sizeof(T))); + v.resize(i + blk); + is.read((char*)&v[i], blk * sizeof(T)); + i += blk; + } +} + +template +void Unserialize_impl(Stream& is, std::vector& v, const V&) +{ + v.clear(); + unsigned int nSize = ReadCompactSize(is); + unsigned int i = 0; + unsigned int nMid = 0; + while (nMid < nSize) + { + nMid += 5000000 / sizeof(T); + if (nMid > nSize) + nMid = nSize; + v.resize(nMid); + for (; i < nMid; i++) + Unserialize(is, v[i]); + } +} + +template +inline void Unserialize(Stream& is, std::vector& v) +{ + Unserialize_impl(is, v, T()); +} + + + +/** + * pair + */ +template +void Serialize(Stream& os, const std::pair& item) +{ + Serialize(os, item.first); + Serialize(os, item.second); +} + +template +void Unserialize(Stream& is, std::pair& item) +{ + Unserialize(is, item.first); + Unserialize(is, item.second); +} + + + +/** + * map + */ +template +void Serialize(Stream& os, const std::map& m) +{ + WriteCompactSize(os, m.size()); + for (typename std::map::const_iterator mi = m.begin(); mi != m.end(); ++mi) + Serialize(os, (*mi)); +} + +template +void Unserialize(Stream& is, std::map& m) +{ + m.clear(); + unsigned int nSize = ReadCompactSize(is); + typename std::map::iterator mi = m.begin(); + for (unsigned int i = 0; i < nSize; i++) + { + std::pair item; + Unserialize(is, item); + mi = m.insert(mi, item); + } +} + + + +/** + * set + */ +template +void Serialize(Stream& os, const std::set& m) +{ + WriteCompactSize(os, m.size()); + for (typename std::set::const_iterator it = m.begin(); it != m.end(); ++it) + Serialize(os, (*it)); +} + +template +void Unserialize(Stream& is, std::set& m) +{ + m.clear(); + unsigned int nSize = ReadCompactSize(is); + typename std::set::iterator it = m.begin(); + for (unsigned int i = 0; i < nSize; i++) + { + K key; + Unserialize(is, key); + it = m.insert(it, key); + } +} + + + +/** + * unique_ptr + */ +template void +Serialize(Stream& os, const std::unique_ptr& p) +{ + Serialize(os, *p); +} + +template +void Unserialize(Stream& is, std::unique_ptr& p) +{ + p.reset(new T(deserialize, is)); +} + + + +/** + * shared_ptr + */ +template void +Serialize(Stream& os, const std::shared_ptr& p) +{ + Serialize(os, *p); +} + +template +void Unserialize(Stream& is, std::shared_ptr& p) +{ + p = std::make_shared(deserialize, is); +} + + + +/** + * Support for ADD_SERIALIZE_METHODS and READWRITE macro + */ +struct CSerActionSerialize +{ + constexpr bool ForRead() const { return false; } +}; +struct CSerActionUnserialize +{ + constexpr bool ForRead() const { return true; } +}; + +template +inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action) +{ + ::Serialize(s, obj); +} + +template +inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action) +{ + ::Unserialize(s, obj); +} + + + + + + + + + +/* ::GetSerializeSize implementations + * + * Computing the serialized size of objects is done through a special stream + * object of type CSizeComputer, which only records the number of bytes written + * to it. + * + * If your Serialize or SerializationOp method has non-trivial overhead for + * serialization, it may be worthwhile to implement a specialized version for + * CSizeComputer, which uses the s.seek() method to record bytes that would + * be written instead. + */ +class CSizeComputer +{ +protected: + size_t nSize; + + const int nType; + const int nVersion; +public: + CSizeComputer(int nTypeIn, int nVersionIn) : nSize(0), nType(nTypeIn), nVersion(nVersionIn) {} + + void write(const char *psz, size_t _nSize) + { + this->nSize += _nSize; + } + + /** Pretend _nSize bytes are written, without specifying them. */ + void seek(size_t _nSize) + { + this->nSize += _nSize; + } + + template + CSizeComputer& operator<<(const T& obj) + { + ::Serialize(*this, obj); + return (*this); + } + + size_t size() const { + return nSize; + } + + int GetVersion() const { return nVersion; } + int GetType() const { return nType; } +}; + +template +void SerializeMany(Stream& s) +{ +} + +template +void SerializeMany(Stream& s, Arg&& arg) +{ + ::Serialize(s, std::forward(arg)); +} + +template +void SerializeMany(Stream& s, Arg&& arg, Args&&... args) +{ + ::Serialize(s, std::forward(arg)); + ::SerializeMany(s, std::forward(args)...); +} + +template +inline void UnserializeMany(Stream& s) +{ +} + +template +inline void UnserializeMany(Stream& s, Arg& arg) +{ + ::Unserialize(s, arg); +} + +template +inline void UnserializeMany(Stream& s, Arg& arg, Args&... args) +{ + ::Unserialize(s, arg); + ::UnserializeMany(s, args...); +} + +template +inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args) +{ + ::SerializeMany(s, std::forward(args)...); +} + +template +inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args) +{ + ::UnserializeMany(s, args...); +} + +template +inline void WriteVarInt(CSizeComputer &s, I n) +{ + s.seek(GetSizeOfVarInt(n)); +} + +inline void WriteCompactSize(CSizeComputer &s, uint64_t nSize) +{ + s.seek(GetSizeOfCompactSize(nSize)); +} + +template +size_t GetSerializeSize(const T& t, int nType, int nVersion = 0) +{ + return (CSizeComputer(nType, nVersion) << t).size(); +} + +template +size_t GetSerializeSize(const S& s, const T& t) +{ + return (CSizeComputer(s.GetType(), s.GetVersion()) << t).size(); +} + +#endif // RAVEN_SERIALIZE_H diff --git a/stratum/algos/sha256q.c b/stratum/algos/sha256q.c new file mode 100644 index 000000000..1cd7f4d26 --- /dev/null +++ b/stratum/algos/sha256q.c @@ -0,0 +1,32 @@ + +#include +#include +#include +#include + +#include "sha256.h" + +#include + +void sha256q_hash(const char* input, char* output, uint32_t len) +{ + unsigned char hash[64]; + + SHA256_CTX ctx_sha256; + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, input, len); + SHA256_Final(hash, &ctx_sha256); + + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, hash, 32); + SHA256_Final(hash, &ctx_sha256); + + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, hash, 32); + SHA256_Final(hash, &ctx_sha256); + + SHA256_Init(&ctx_sha256); + SHA256_Update(&ctx_sha256, hash, 32); + SHA256_Final((unsigned char*)output, &ctx_sha256); +} + diff --git a/stratum/algos/sha256q.h b/stratum/algos/sha256q.h new file mode 100644 index 000000000..23fd6c1b9 --- /dev/null +++ b/stratum/algos/sha256q.h @@ -0,0 +1,16 @@ +#ifndef SHA256Q_H +#define SHA256Q_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void sha256q_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_blake.h b/stratum/algos/sph_blake.h new file mode 100644 index 000000000..d8d794399 --- /dev/null +++ b/stratum/algos/sph_blake.h @@ -0,0 +1,327 @@ +/* $Id: sph_blake.h 252 2011-06-07 17:55:14Z tp $ */ +/** + * BLAKE interface. BLAKE is a family of functions which differ by their + * output size; this implementation defines BLAKE for output sizes 224, + * 256, 384 and 512 bits. This implementation conforms to the "third + * round" specification. + * + * ==========================(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_blake.h + * @author Thomas Pornin + */ + +#ifndef SPH_BLAKE_H__ +#define SPH_BLAKE_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for BLAKE-224. + */ +#define SPH_SIZE_blake224 224 + +/** + * Output size (in bits) for BLAKE-256. + */ +#define SPH_SIZE_blake256 256 + +#if SPH_64 + +/** + * Output size (in bits) for BLAKE-384. + */ +#define SPH_SIZE_blake384 384 + +/** + * Output size (in bits) for BLAKE-512. + */ +#define SPH_SIZE_blake512 512 + +#endif + +/** + * This structure is a context for BLAKE-224 and BLAKE-256 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a BLAKE computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running BLAKE + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 H[8]; + sph_u32 S[4]; + sph_u32 T0, T1; +#endif +} sph_blake_small_context; + +/** + * This structure is a context for BLAKE-224 computations. It is + * identical to the common sph_blake_small_context. + */ +typedef sph_blake_small_context sph_blake224_context; + +/** + * This structure is a context for BLAKE-256 computations. It is + * identical to the common sph_blake_small_context. + */ +typedef sph_blake_small_context sph_blake256_context; + +#if SPH_64 + +/** + * This structure is a context for BLAKE-384 and BLAKE-512 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a BLAKE computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running BLAKE + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u64 H[8]; + sph_u64 S[4]; + sph_u64 T0, T1; +#endif +} sph_blake_big_context; + +/** + * This structure is a context for BLAKE-384 computations. It is + * identical to the common sph_blake_small_context. + */ +typedef sph_blake_big_context sph_blake384_context; + +/** + * This structure is a context for BLAKE-512 computations. It is + * identical to the common sph_blake_small_context. + */ +typedef sph_blake_big_context sph_blake512_context; + +#endif + +/** + * Initialize a BLAKE-224 context. This process performs no memory allocation. + * + * @param cc the BLAKE-224 context (pointer to a + * sph_blake224_context) + */ +void sph_blake224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BLAKE-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_blake224(void *cc, const void *data, size_t len); + +/** + * Terminate the current BLAKE-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the BLAKE-224 context + * @param dst the destination buffer + */ +void sph_blake224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BLAKE-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_blake224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a BLAKE-256 context. This process performs no memory allocation. + * + * @param cc the BLAKE-256 context (pointer to a + * sph_blake256_context) + */ +void sph_blake256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BLAKE-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_blake256(void *cc, const void *data, size_t len); + +/** + * Terminate the current BLAKE-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the BLAKE-256 context + * @param dst the destination buffer + */ +void sph_blake256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BLAKE-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_blake256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#if SPH_64 + +/** + * Initialize a BLAKE-384 context. This process performs no memory allocation. + * + * @param cc the BLAKE-384 context (pointer to a + * sph_blake384_context) + */ +void sph_blake384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BLAKE-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_blake384(void *cc, const void *data, size_t len); + +/** + * Terminate the current BLAKE-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the BLAKE-384 context + * @param dst the destination buffer + */ +void sph_blake384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BLAKE-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_blake384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a BLAKE-512 context. This process performs no memory allocation. + * + * @param cc the BLAKE-512 context (pointer to a + * sph_blake512_context) + */ +void sph_blake512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BLAKE-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_blake512(void *cc, const void *data, size_t len); + +/** + * Terminate the current BLAKE-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the BLAKE-512 context + * @param dst the destination buffer + */ +void sph_blake512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BLAKE-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_blake512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_bmw.h b/stratum/algos/sph_bmw.h new file mode 100644 index 000000000..d386b0c14 --- /dev/null +++ b/stratum/algos/sph_bmw.h @@ -0,0 +1,328 @@ +/* $Id: sph_bmw.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * BMW interface. BMW (aka "Blue Midnight Wish") is a family of + * functions which differ by their output size; this implementation + * defines BMW for output sizes 224, 256, 384 and 512 bits. + * + * ==========================(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_bmw.h + * @author Thomas Pornin + */ + +#ifndef SPH_BMW_H__ +#define SPH_BMW_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for BMW-224. + */ +#define SPH_SIZE_bmw224 224 + +/** + * Output size (in bits) for BMW-256. + */ +#define SPH_SIZE_bmw256 256 + +#if SPH_64 + +/** + * Output size (in bits) for BMW-384. + */ +#define SPH_SIZE_bmw384 384 + +/** + * Output size (in bits) for BMW-512. + */ +#define SPH_SIZE_bmw512 512 + +#endif + +/** + * This structure is a context for BMW-224 and BMW-256 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a BMW computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running BMW + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 H[16]; +#if SPH_64 + sph_u64 bit_count; +#else + sph_u32 bit_count_high, bit_count_low; +#endif +#endif +} sph_bmw_small_context; + +/** + * This structure is a context for BMW-224 computations. It is + * identical to the common sph_bmw_small_context. + */ +typedef sph_bmw_small_context sph_bmw224_context; + +/** + * This structure is a context for BMW-256 computations. It is + * identical to the common sph_bmw_small_context. + */ +typedef sph_bmw_small_context sph_bmw256_context; + +#if SPH_64 + +/** + * This structure is a context for BMW-384 and BMW-512 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a BMW computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running BMW + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u64 H[16]; + sph_u64 bit_count; +#endif +} sph_bmw_big_context; + +/** + * This structure is a context for BMW-384 computations. It is + * identical to the common sph_bmw_small_context. + */ +typedef sph_bmw_big_context sph_bmw384_context; + +/** + * This structure is a context for BMW-512 computations. It is + * identical to the common sph_bmw_small_context. + */ +typedef sph_bmw_big_context sph_bmw512_context; + +#endif + +/** + * Initialize a BMW-224 context. This process performs no memory allocation. + * + * @param cc the BMW-224 context (pointer to a + * sph_bmw224_context) + */ +void sph_bmw224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BMW-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_bmw224(void *cc, const void *data, size_t len); + +/** + * Terminate the current BMW-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the BMW-224 context + * @param dst the destination buffer + */ +void sph_bmw224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BMW-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_bmw224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a BMW-256 context. This process performs no memory allocation. + * + * @param cc the BMW-256 context (pointer to a + * sph_bmw256_context) + */ +void sph_bmw256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BMW-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_bmw256(void *cc, const void *data, size_t len); + +/** + * Terminate the current BMW-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the BMW-256 context + * @param dst the destination buffer + */ +void sph_bmw256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BMW-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_bmw256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#if SPH_64 + +/** + * Initialize a BMW-384 context. This process performs no memory allocation. + * + * @param cc the BMW-384 context (pointer to a + * sph_bmw384_context) + */ +void sph_bmw384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BMW-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_bmw384(void *cc, const void *data, size_t len); + +/** + * Terminate the current BMW-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the BMW-384 context + * @param dst the destination buffer + */ +void sph_bmw384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BMW-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_bmw384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a BMW-512 context. This process performs no memory allocation. + * + * @param cc the BMW-512 context (pointer to a + * sph_bmw512_context) + */ +void sph_bmw512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the BMW-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_bmw512(void *cc, const void *data, size_t len); + +/** + * Terminate the current BMW-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the BMW-512 context + * @param dst the destination buffer + */ +void sph_bmw512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the BMW-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_bmw512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_cubehash.h b/stratum/algos/sph_cubehash.h new file mode 100644 index 000000000..487a1946a --- /dev/null +++ b/stratum/algos/sph_cubehash.h @@ -0,0 +1,292 @@ +/* $Id: sph_cubehash.h 180 2010-05-08 02:29:25Z tp $ */ +/** + * CubeHash interface. CubeHash is a family of functions which differ by + * their output size; this implementation defines CubeHash for output + * sizes 224, 256, 384 and 512 bits, with the "standard parameters" + * (CubeHash16/32 with the CubeHash specification notations). + * + * ==========================(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_cubehash.h + * @author Thomas Pornin + */ + +#ifndef SPH_CUBEHASH_H__ +#define SPH_CUBEHASH_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for CubeHash-224. + */ +#define SPH_SIZE_cubehash224 224 + +/** + * Output size (in bits) for CubeHash-256. + */ +#define SPH_SIZE_cubehash256 256 + +/** + * Output size (in bits) for CubeHash-384. + */ +#define SPH_SIZE_cubehash384 384 + +/** + * Output size (in bits) for CubeHash-512. + */ +#define SPH_SIZE_cubehash512 512 + +/** + * This structure is a context for CubeHash computations: it contains the + * intermediate values and some data from the last entered block. Once + * a CubeHash computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running CubeHash computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 state[32]; +#endif +} sph_cubehash_context; + +/** + * Type for a CubeHash-224 context (identical to the common context). + */ +typedef sph_cubehash_context sph_cubehash224_context; + +/** + * Type for a CubeHash-256 context (identical to the common context). + */ +typedef sph_cubehash_context sph_cubehash256_context; + +/** + * Type for a CubeHash-384 context (identical to the common context). + */ +typedef sph_cubehash_context sph_cubehash384_context; + +/** + * Type for a CubeHash-512 context (identical to the common context). + */ +typedef sph_cubehash_context sph_cubehash512_context; + +/** + * Initialize a CubeHash-224 context. This process performs no memory + * allocation. + * + * @param cc the CubeHash-224 context (pointer to a + * sph_cubehash224_context) + */ +void sph_cubehash224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the CubeHash-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_cubehash224(void *cc, const void *data, size_t len); + +/** + * Terminate the current CubeHash-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the CubeHash-224 context + * @param dst the destination buffer + */ +void sph_cubehash224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the CubeHash-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_cubehash224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a CubeHash-256 context. This process performs no memory + * allocation. + * + * @param cc the CubeHash-256 context (pointer to a + * sph_cubehash256_context) + */ +void sph_cubehash256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the CubeHash-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_cubehash256(void *cc, const void *data, size_t len); + +/** + * Terminate the current CubeHash-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the CubeHash-256 context + * @param dst the destination buffer + */ +void sph_cubehash256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the CubeHash-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_cubehash256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a CubeHash-384 context. This process performs no memory + * allocation. + * + * @param cc the CubeHash-384 context (pointer to a + * sph_cubehash384_context) + */ +void sph_cubehash384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the CubeHash-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_cubehash384(void *cc, const void *data, size_t len); + +/** + * Terminate the current CubeHash-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the CubeHash-384 context + * @param dst the destination buffer + */ +void sph_cubehash384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the CubeHash-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_cubehash384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a CubeHash-512 context. This process performs no memory + * allocation. + * + * @param cc the CubeHash-512 context (pointer to a + * sph_cubehash512_context) + */ +void sph_cubehash512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the CubeHash-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_cubehash512(void *cc, const void *data, size_t len); + +/** + * Terminate the current CubeHash-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the CubeHash-512 context + * @param dst the destination buffer + */ +void sph_cubehash512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the CubeHash-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_cubehash512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_echo.h b/stratum/algos/sph_echo.h new file mode 100644 index 000000000..1ae1e3dd6 --- /dev/null +++ b/stratum/algos/sph_echo.h @@ -0,0 +1,320 @@ +/* $Id: sph_echo.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * ECHO interface. ECHO is a family of functions which differ by + * their output size; this implementation defines ECHO for output + * sizes 224, 256, 384 and 512 bits. + * + * ==========================(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_echo.h + * @author Thomas Pornin + */ + +#ifndef SPH_ECHO_H__ +#define SPH_ECHO_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for ECHO-224. + */ +#define SPH_SIZE_echo224 224 + +/** + * Output size (in bits) for ECHO-256. + */ +#define SPH_SIZE_echo256 256 + +/** + * Output size (in bits) for ECHO-384. + */ +#define SPH_SIZE_echo384 384 + +/** + * Output size (in bits) for ECHO-512. + */ +#define SPH_SIZE_echo512 512 + +/** + * This structure is a context for ECHO computations: it contains the + * intermediate values and some data from the last entered block. Once + * an ECHO computation has been performed, the context can be reused for + * another computation. This specific structure is used for ECHO-224 + * and ECHO-256. + * + * The contents of this structure are private. A running ECHO computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[192]; /* first field, for alignment */ + size_t ptr; + union { + sph_u32 Vs[4][4]; +#if SPH_64 + sph_u64 Vb[4][2]; +#endif + } u; + sph_u32 C0, C1, C2, C3; +#endif +} sph_echo_small_context; + +/** + * This structure is a context for ECHO computations: it contains the + * intermediate values and some data from the last entered block. Once + * an ECHO computation has been performed, the context can be reused for + * another computation. This specific structure is used for ECHO-384 + * and ECHO-512. + * + * The contents of this structure are private. A running ECHO computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + union { + sph_u32 Vs[8][4]; +#if SPH_64 + sph_u64 Vb[8][2]; +#endif + } u; + sph_u32 C0, C1, C2, C3; +#endif +} sph_echo_big_context; + +/** + * Type for a ECHO-224 context (identical to the common "small" context). + */ +typedef sph_echo_small_context sph_echo224_context; + +/** + * Type for a ECHO-256 context (identical to the common "small" context). + */ +typedef sph_echo_small_context sph_echo256_context; + +/** + * Type for a ECHO-384 context (identical to the common "big" context). + */ +typedef sph_echo_big_context sph_echo384_context; + +/** + * Type for a ECHO-512 context (identical to the common "big" context). + */ +typedef sph_echo_big_context sph_echo512_context; + +/** + * Initialize an ECHO-224 context. This process performs no memory allocation. + * + * @param cc the ECHO-224 context (pointer to a + * sph_echo224_context) + */ +void sph_echo224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the ECHO-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_echo224(void *cc, const void *data, size_t len); + +/** + * Terminate the current ECHO-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the ECHO-224 context + * @param dst the destination buffer + */ +void sph_echo224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the ECHO-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_echo224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize an ECHO-256 context. This process performs no memory allocation. + * + * @param cc the ECHO-256 context (pointer to a + * sph_echo256_context) + */ +void sph_echo256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the ECHO-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_echo256(void *cc, const void *data, size_t len); + +/** + * Terminate the current ECHO-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the ECHO-256 context + * @param dst the destination buffer + */ +void sph_echo256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the ECHO-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_echo256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize an ECHO-384 context. This process performs no memory allocation. + * + * @param cc the ECHO-384 context (pointer to a + * sph_echo384_context) + */ +void sph_echo384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the ECHO-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_echo384(void *cc, const void *data, size_t len); + +/** + * Terminate the current ECHO-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the ECHO-384 context + * @param dst the destination buffer + */ +void sph_echo384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the ECHO-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_echo384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize an ECHO-512 context. This process performs no memory allocation. + * + * @param cc the ECHO-512 context (pointer to a + * sph_echo512_context) + */ +void sph_echo512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the ECHO-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_echo512(void *cc, const void *data, size_t len); + +/** + * Terminate the current ECHO-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the ECHO-512 context + * @param dst the destination buffer + */ +void sph_echo512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the ECHO-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_echo512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_fugue.h b/stratum/algos/sph_fugue.h new file mode 100644 index 000000000..c8ff395e2 --- /dev/null +++ b/stratum/algos/sph_fugue.h @@ -0,0 +1,81 @@ +#ifndef SPH_FUGUE_H__ +#define SPH_FUGUE_H__ + +#include +#include "sph_types.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#define SPH_SIZE_fugue224 224 + +#define SPH_SIZE_fugue256 256 + +#define SPH_SIZE_fugue384 384 + +#define SPH_SIZE_fugue512 512 + +typedef struct { +#ifndef DOXYGEN_IGNORE + sph_u32 partial; + unsigned partial_len; + unsigned round_shift; + sph_u32 S[36]; +#if SPH_64 + sph_u64 bit_count; +#else + sph_u32 bit_count_high, bit_count_low; +#endif +#endif +} sph_fugue_context; + +typedef sph_fugue_context sph_fugue224_context; + +typedef sph_fugue_context sph_fugue256_context; + +typedef sph_fugue_context sph_fugue384_context; + +typedef sph_fugue_context sph_fugue512_context; + +void sph_fugue224_init(void *cc); + +void sph_fugue224(void *cc, const void *data, size_t len); + +void sph_fugue224_close(void *cc, void *dst); + +void sph_fugue224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +void sph_fugue256_init(void *cc); + +void sph_fugue256(void *cc, const void *data, size_t len); + +void sph_fugue256_close(void *cc, void *dst); + +void sph_fugue256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +void sph_fugue384_init(void *cc); + +void sph_fugue384(void *cc, const void *data, size_t len); + +void sph_fugue384_close(void *cc, void *dst); + +void sph_fugue384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +void sph_fugue512_init(void *cc); + +void sph_fugue512(void *cc, const void *data, size_t len); + +void sph_fugue512_close(void *cc, void *dst); + +void sph_fugue512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_groestl.h b/stratum/algos/sph_groestl.h new file mode 100644 index 000000000..495f05e21 --- /dev/null +++ b/stratum/algos/sph_groestl.h @@ -0,0 +1,329 @@ +/* $Id: sph_groestl.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * Groestl interface. This code implements Groestl with the recommended + * parameters for SHA-3, with outputs of 224, 256, 384 and 512 bits. + * + * ==========================(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_groestl.h + * @author Thomas Pornin + */ + +#ifndef SPH_GROESTL_H__ +#define SPH_GROESTL_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for Groestl-224. + */ +#define SPH_SIZE_groestl224 224 + +/** + * Output size (in bits) for Groestl-256. + */ +#define SPH_SIZE_groestl256 256 + +/** + * Output size (in bits) for Groestl-384. + */ +#define SPH_SIZE_groestl384 384 + +/** + * Output size (in bits) for Groestl-512. + */ +#define SPH_SIZE_groestl512 512 + +/** + * This structure is a context for Groestl-224 and Groestl-256 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a Groestl computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running Groestl + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + union { +#if SPH_64 + sph_u64 wide[8]; +#endif + sph_u32 narrow[16]; + } state; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_groestl_small_context; + +/** + * This structure is a context for Groestl-224 computations. It is + * identical to the common sph_groestl_small_context. + */ +typedef sph_groestl_small_context sph_groestl224_context; + +/** + * This structure is a context for Groestl-256 computations. It is + * identical to the common sph_groestl_small_context. + */ +typedef sph_groestl_small_context sph_groestl256_context; + +/** + * This structure is a context for Groestl-384 and Groestl-512 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a Groestl computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running Groestl + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + union { +#if SPH_64 + sph_u64 wide[16]; +#endif + sph_u32 narrow[32]; + } state; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_groestl_big_context; + +/** + * This structure is a context for Groestl-384 computations. It is + * identical to the common sph_groestl_small_context. + */ +typedef sph_groestl_big_context sph_groestl384_context; + +/** + * This structure is a context for Groestl-512 computations. It is + * identical to the common sph_groestl_small_context. + */ +typedef sph_groestl_big_context sph_groestl512_context; + +/** + * Initialize a Groestl-224 context. This process performs no memory allocation. + * + * @param cc the Groestl-224 context (pointer to a + * sph_groestl224_context) + */ +void sph_groestl224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Groestl-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_groestl224(void *cc, const void *data, size_t len); + +/** + * Terminate the current Groestl-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the Groestl-224 context + * @param dst the destination buffer + */ +void sph_groestl224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Groestl-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_groestl224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Groestl-256 context. This process performs no memory allocation. + * + * @param cc the Groestl-256 context (pointer to a + * sph_groestl256_context) + */ +void sph_groestl256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Groestl-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_groestl256(void *cc, const void *data, size_t len); + +/** + * Terminate the current Groestl-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the Groestl-256 context + * @param dst the destination buffer + */ +void sph_groestl256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Groestl-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_groestl256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Groestl-384 context. This process performs no memory allocation. + * + * @param cc the Groestl-384 context (pointer to a + * sph_groestl384_context) + */ +void sph_groestl384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Groestl-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_groestl384(void *cc, const void *data, size_t len); + +/** + * Terminate the current Groestl-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the Groestl-384 context + * @param dst the destination buffer + */ +void sph_groestl384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Groestl-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_groestl384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Groestl-512 context. This process performs no memory allocation. + * + * @param cc the Groestl-512 context (pointer to a + * sph_groestl512_context) + */ +void sph_groestl512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Groestl-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_groestl512(void *cc, const void *data, size_t len); + +/** + * Terminate the current Groestl-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the Groestl-512 context + * @param dst the destination buffer + */ +void sph_groestl512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Groestl-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_groestl512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_hamsi.h b/stratum/algos/sph_hamsi.h new file mode 100644 index 000000000..111c30c40 --- /dev/null +++ b/stratum/algos/sph_hamsi.h @@ -0,0 +1,319 @@ +/* $Id: sph_hamsi.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * Hamsi interface. This code implements Hamsi with the recommended + * parameters for SHA-3, with outputs of 224, 256, 384 and 512 bits. + * + * ==========================(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_hamsi.h + * @author Thomas Pornin + */ + +#ifndef SPH_HAMSI_H__ +#define SPH_HAMSI_H__ + +#include +#include "sph_types.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * Output size (in bits) for Hamsi-224. + */ +#define SPH_SIZE_hamsi224 224 + +/** + * Output size (in bits) for Hamsi-256. + */ +#define SPH_SIZE_hamsi256 256 + +/** + * Output size (in bits) for Hamsi-384. + */ +#define SPH_SIZE_hamsi384 384 + +/** + * Output size (in bits) for Hamsi-512. + */ +#define SPH_SIZE_hamsi512 512 + +/** + * This structure is a context for Hamsi-224 and Hamsi-256 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a Hamsi computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running Hamsi + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char partial[4]; + size_t partial_len; + sph_u32 h[8]; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_hamsi_small_context; + +/** + * This structure is a context for Hamsi-224 computations. It is + * identical to the common sph_hamsi_small_context. + */ +typedef sph_hamsi_small_context sph_hamsi224_context; + +/** + * This structure is a context for Hamsi-256 computations. It is + * identical to the common sph_hamsi_small_context. + */ +typedef sph_hamsi_small_context sph_hamsi256_context; + +/** + * This structure is a context for Hamsi-384 and Hamsi-512 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a Hamsi computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running Hamsi + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char partial[8]; + size_t partial_len; + sph_u32 h[16]; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_hamsi_big_context; + +/** + * This structure is a context for Hamsi-384 computations. It is + * identical to the common sph_hamsi_small_context. + */ +typedef sph_hamsi_big_context sph_hamsi384_context; + +/** + * This structure is a context for Hamsi-512 computations. It is + * identical to the common sph_hamsi_small_context. + */ +typedef sph_hamsi_big_context sph_hamsi512_context; + +/** + * Initialize a Hamsi-224 context. This process performs no memory allocation. + * + * @param cc the Hamsi-224 context (pointer to a + * sph_hamsi224_context) + */ +void sph_hamsi224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Hamsi-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_hamsi224(void *cc, const void *data, size_t len); + +/** + * Terminate the current Hamsi-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the Hamsi-224 context + * @param dst the destination buffer + */ +void sph_hamsi224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Hamsi-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_hamsi224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Hamsi-256 context. This process performs no memory allocation. + * + * @param cc the Hamsi-256 context (pointer to a + * sph_hamsi256_context) + */ +void sph_hamsi256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Hamsi-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_hamsi256(void *cc, const void *data, size_t len); + +/** + * Terminate the current Hamsi-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the Hamsi-256 context + * @param dst the destination buffer + */ +void sph_hamsi256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Hamsi-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_hamsi256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Hamsi-384 context. This process performs no memory allocation. + * + * @param cc the Hamsi-384 context (pointer to a + * sph_hamsi384_context) + */ +void sph_hamsi384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Hamsi-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_hamsi384(void *cc, const void *data, size_t len); + +/** + * Terminate the current Hamsi-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the Hamsi-384 context + * @param dst the destination buffer + */ +void sph_hamsi384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Hamsi-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_hamsi384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Hamsi-512 context. This process performs no memory allocation. + * + * @param cc the Hamsi-512 context (pointer to a + * sph_hamsi512_context) + */ +void sph_hamsi512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Hamsi-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_hamsi512(void *cc, const void *data, size_t len); + +/** + * Terminate the current Hamsi-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the Hamsi-512 context + * @param dst the destination buffer + */ +void sph_hamsi512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Hamsi-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_hamsi512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_jh.h b/stratum/algos/sph_jh.h new file mode 100644 index 000000000..82fae58df --- /dev/null +++ b/stratum/algos/sph_jh.h @@ -0,0 +1,298 @@ +/* $Id: sph_jh.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * JH interface. JH is a family of functions which differ by + * their output size; this implementation defines JH for output + * sizes 224, 256, 384 and 512 bits. + * + * ==========================(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_jh.h + * @author Thomas Pornin + */ + +#ifndef SPH_JH_H__ +#define SPH_JH_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for JH-224. + */ +#define SPH_SIZE_jh224 224 + +/** + * Output size (in bits) for JH-256. + */ +#define SPH_SIZE_jh256 256 + +/** + * Output size (in bits) for JH-384. + */ +#define SPH_SIZE_jh384 384 + +/** + * Output size (in bits) for JH-512. + */ +#define SPH_SIZE_jh512 512 + +/** + * This structure is a context for JH computations: it contains the + * intermediate values and some data from the last entered block. Once + * a JH computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running JH computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + union { +#if SPH_64 + sph_u64 wide[16]; +#endif + sph_u32 narrow[32]; + } H; +#if SPH_64 + sph_u64 block_count; +#else + sph_u32 block_count_high, block_count_low; +#endif +#endif +} sph_jh_context; + +/** + * Type for a JH-224 context (identical to the common context). + */ +typedef sph_jh_context sph_jh224_context; + +/** + * Type for a JH-256 context (identical to the common context). + */ +typedef sph_jh_context sph_jh256_context; + +/** + * Type for a JH-384 context (identical to the common context). + */ +typedef sph_jh_context sph_jh384_context; + +/** + * Type for a JH-512 context (identical to the common context). + */ +typedef sph_jh_context sph_jh512_context; + +/** + * Initialize a JH-224 context. This process performs no memory allocation. + * + * @param cc the JH-224 context (pointer to a + * sph_jh224_context) + */ +void sph_jh224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the JH-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_jh224(void *cc, const void *data, size_t len); + +/** + * Terminate the current JH-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the JH-224 context + * @param dst the destination buffer + */ +void sph_jh224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the JH-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_jh224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a JH-256 context. This process performs no memory allocation. + * + * @param cc the JH-256 context (pointer to a + * sph_jh256_context) + */ +void sph_jh256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the JH-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_jh256(void *cc, const void *data, size_t len); + +/** + * Terminate the current JH-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the JH-256 context + * @param dst the destination buffer + */ +void sph_jh256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the JH-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_jh256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a JH-384 context. This process performs no memory allocation. + * + * @param cc the JH-384 context (pointer to a + * sph_jh384_context) + */ +void sph_jh384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the JH-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_jh384(void *cc, const void *data, size_t len); + +/** + * Terminate the current JH-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the JH-384 context + * @param dst the destination buffer + */ +void sph_jh384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the JH-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_jh384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a JH-512 context. This process performs no memory allocation. + * + * @param cc the JH-512 context (pointer to a + * sph_jh512_context) + */ +void sph_jh512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the JH-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_jh512(void *cc, const void *data, size_t len); + +/** + * Terminate the current JH-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the JH-512 context + * @param dst the destination buffer + */ +void sph_jh512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the JH-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_jh512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_keccak.h b/stratum/algos/sph_keccak.h new file mode 100644 index 000000000..bdafdb88d --- /dev/null +++ b/stratum/algos/sph_keccak.h @@ -0,0 +1,293 @@ +/* $Id: sph_keccak.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * Keccak interface. This is the interface for Keccak with the + * recommended parameters for SHA-3, with output lengths 224, 256, + * 384 and 512 bits. + * + * ==========================(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_keccak.h + * @author Thomas Pornin + */ + +#ifndef SPH_KECCAK_H__ +#define SPH_KECCAK_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for Keccak-224. + */ +#define SPH_SIZE_keccak224 224 + +/** + * Output size (in bits) for Keccak-256. + */ +#define SPH_SIZE_keccak256 256 + +/** + * Output size (in bits) for Keccak-384. + */ +#define SPH_SIZE_keccak384 384 + +/** + * Output size (in bits) for Keccak-512. + */ +#define SPH_SIZE_keccak512 512 + +/** + * This structure is a context for Keccak computations: it contains the + * intermediate values and some data from the last entered block. Once a + * Keccak computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running Keccak computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[144]; /* first field, for alignment */ + size_t ptr, lim; + union { +#if SPH_64 + sph_u64 wide[25]; +#endif + sph_u32 narrow[50]; + } u; +#endif +} sph_keccak_context; + +/** + * Type for a Keccak-224 context (identical to the common context). + */ +typedef sph_keccak_context sph_keccak224_context; + +/** + * Type for a Keccak-256 context (identical to the common context). + */ +typedef sph_keccak_context sph_keccak256_context; + +/** + * Type for a Keccak-384 context (identical to the common context). + */ +typedef sph_keccak_context sph_keccak384_context; + +/** + * Type for a Keccak-512 context (identical to the common context). + */ +typedef sph_keccak_context sph_keccak512_context; + +/** + * Initialize a Keccak-224 context. This process performs no memory allocation. + * + * @param cc the Keccak-224 context (pointer to a + * sph_keccak224_context) + */ +void sph_keccak224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Keccak-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_keccak224(void *cc, const void *data, size_t len); + +/** + * Terminate the current Keccak-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the Keccak-224 context + * @param dst the destination buffer + */ +void sph_keccak224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Keccak-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_keccak224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Keccak-256 context. This process performs no memory allocation. + * + * @param cc the Keccak-256 context (pointer to a + * sph_keccak256_context) + */ +void sph_keccak256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Keccak-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_keccak256(void *cc, const void *data, size_t len); + +/** + * Terminate the current Keccak-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the Keccak-256 context + * @param dst the destination buffer + */ +void sph_keccak256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Keccak-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_keccak256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Keccak-384 context. This process performs no memory allocation. + * + * @param cc the Keccak-384 context (pointer to a + * sph_keccak384_context) + */ +void sph_keccak384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Keccak-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_keccak384(void *cc, const void *data, size_t len); + +/** + * Terminate the current Keccak-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the Keccak-384 context + * @param dst the destination buffer + */ +void sph_keccak384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Keccak-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_keccak384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Keccak-512 context. This process performs no memory allocation. + * + * @param cc the Keccak-512 context (pointer to a + * sph_keccak512_context) + */ +void sph_keccak512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Keccak-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_keccak512(void *cc, const void *data, size_t len); + +/** + * Terminate the current Keccak-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the Keccak-512 context + * @param dst the destination buffer + */ +void sph_keccak512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Keccak-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_keccak512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_luffa.h b/stratum/algos/sph_luffa.h new file mode 100644 index 000000000..a32fd7b16 --- /dev/null +++ b/stratum/algos/sph_luffa.h @@ -0,0 +1,296 @@ +/* $Id: sph_luffa.h 154 2010-04-26 17:00:24Z tp $ */ +/** + * Luffa interface. Luffa is a family of functions which differ by + * their output size; this implementation defines Luffa for output + * sizes 224, 256, 384 and 512 bits. + * + * ==========================(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_luffa.h + * @author Thomas Pornin + */ + +#ifndef SPH_LUFFA_H__ +#define SPH_LUFFA_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for Luffa-224. + */ +#define SPH_SIZE_luffa224 224 + +/** + * Output size (in bits) for Luffa-256. + */ +#define SPH_SIZE_luffa256 256 + +/** + * Output size (in bits) for Luffa-384. + */ +#define SPH_SIZE_luffa384 384 + +/** + * Output size (in bits) for Luffa-512. + */ +#define SPH_SIZE_luffa512 512 + +/** + * This structure is a context for Luffa-224 computations: it contains + * the intermediate values and some data from the last entered block. + * Once a Luffa computation has been performed, the context can be + * reused for another computation. + * + * The contents of this structure are private. A running Luffa + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[3][8]; +#endif +} sph_luffa224_context; + +/** + * This structure is a context for Luffa-256 computations. It is + * identical to sph_luffa224_context. + */ +typedef sph_luffa224_context sph_luffa256_context; + +/** + * This structure is a context for Luffa-384 computations. + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[4][8]; +#endif +} sph_luffa384_context; + +/** + * This structure is a context for Luffa-512 computations. + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[5][8]; +#endif +} sph_luffa512_context; + +/** + * Initialize a Luffa-224 context. This process performs no memory allocation. + * + * @param cc the Luffa-224 context (pointer to a + * sph_luffa224_context) + */ +void sph_luffa224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Luffa-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_luffa224(void *cc, const void *data, size_t len); + +/** + * Terminate the current Luffa-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the Luffa-224 context + * @param dst the destination buffer + */ +void sph_luffa224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Luffa-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_luffa224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Luffa-256 context. This process performs no memory allocation. + * + * @param cc the Luffa-256 context (pointer to a + * sph_luffa256_context) + */ +void sph_luffa256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Luffa-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_luffa256(void *cc, const void *data, size_t len); + +/** + * Terminate the current Luffa-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the Luffa-256 context + * @param dst the destination buffer + */ +void sph_luffa256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Luffa-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_luffa256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Luffa-384 context. This process performs no memory allocation. + * + * @param cc the Luffa-384 context (pointer to a + * sph_luffa384_context) + */ +void sph_luffa384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Luffa-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_luffa384(void *cc, const void *data, size_t len); + +/** + * Terminate the current Luffa-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the Luffa-384 context + * @param dst the destination buffer + */ +void sph_luffa384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Luffa-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_luffa384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Luffa-512 context. This process performs no memory allocation. + * + * @param cc the Luffa-512 context (pointer to a + * sph_luffa512_context) + */ +void sph_luffa512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Luffa-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_luffa512(void *cc, const void *data, size_t len); + +/** + * Terminate the current Luffa-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the Luffa-512 context + * @param dst the destination buffer + */ +void sph_luffa512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Luffa-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_luffa512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_panama.c b/stratum/algos/sph_panama.c new file mode 100644 index 000000000..0eca16a9f --- /dev/null +++ b/stratum/algos/sph_panama.c @@ -0,0 +1,334 @@ +/* $Id: panama.c 216 2010-06-08 09:46:57Z tp $ */ +/* + * PANAMA implementation. + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_panama.h" + +#define LVAR17(b) sph_u32 \ + b ## 0, b ## 1, b ## 2, b ## 3, b ## 4, b ## 5, \ + b ## 6, b ## 7, b ## 8, b ## 9, b ## 10, b ## 11, \ + b ## 12, b ## 13, b ## 14, b ## 15, b ## 16; + +#define LVARS \ + LVAR17(a) \ + LVAR17(g) \ + LVAR17(p) \ + LVAR17(t) + +#define M17(macro) do { \ + macro( 0, 1, 2, 4); \ + macro( 1, 2, 3, 5); \ + macro( 2, 3, 4, 6); \ + macro( 3, 4, 5, 7); \ + macro( 4, 5, 6, 8); \ + macro( 5, 6, 7, 9); \ + macro( 6, 7, 8, 10); \ + macro( 7, 8, 9, 11); \ + macro( 8, 9, 10, 12); \ + macro( 9, 10, 11, 13); \ + macro(10, 11, 12, 14); \ + macro(11, 12, 13, 15); \ + macro(12, 13, 14, 16); \ + macro(13, 14, 15, 0); \ + macro(14, 15, 16, 1); \ + macro(15, 16, 0, 2); \ + macro(16, 0, 1, 3); \ + } while (0) + +#define BUPDATE1(n0, n2) do { \ + sc->buffer[ptr24][n0] ^= sc->buffer[ptr31][n2]; \ + sc->buffer[ptr31][n2] ^= INW1(n2); \ + } while (0) + +#define BUPDATE do { \ + BUPDATE1(0, 2); \ + BUPDATE1(1, 3); \ + BUPDATE1(2, 4); \ + BUPDATE1(3, 5); \ + BUPDATE1(4, 6); \ + BUPDATE1(5, 7); \ + BUPDATE1(6, 0); \ + BUPDATE1(7, 1); \ + } while (0) + +#define RSTATE(n0, n1, n2, n4) (a ## n0 = sc->state[n0]) + +#define WSTATE(n0, n1, n2, n4) (sc->state[n0] = a ## n0) + +#define GAMMA(n0, n1, n2, n4) \ + (g ## n0 = a ## n0 ^ (a ## n1 | SPH_T32(~a ## n2))) + +#define PI_ALL do { \ + p0 = g0; \ + p1 = SPH_ROTL32( g7, 1); \ + p2 = SPH_ROTL32(g14, 3); \ + p3 = SPH_ROTL32( g4, 6); \ + p4 = SPH_ROTL32(g11, 10); \ + p5 = SPH_ROTL32( g1, 15); \ + p6 = SPH_ROTL32( g8, 21); \ + p7 = SPH_ROTL32(g15, 28); \ + p8 = SPH_ROTL32( g5, 4); \ + p9 = SPH_ROTL32(g12, 13); \ + p10 = SPH_ROTL32( g2, 23); \ + p11 = SPH_ROTL32( g9, 2); \ + p12 = SPH_ROTL32(g16, 14); \ + p13 = SPH_ROTL32( g6, 27); \ + p14 = SPH_ROTL32(g13, 9); \ + p15 = SPH_ROTL32( g3, 24); \ + p16 = SPH_ROTL32(g10, 8); \ + } while (0) + +#define THETA(n0, n1, n2, n4) \ + (t ## n0 = p ## n0 ^ p ## n1 ^ p ## n4) + +#define SIGMA_ALL do { \ + a0 = t0 ^ 1; \ + a1 = t1 ^ INW2(0); \ + a2 = t2 ^ INW2(1); \ + a3 = t3 ^ INW2(2); \ + a4 = t4 ^ INW2(3); \ + a5 = t5 ^ INW2(4); \ + a6 = t6 ^ INW2(5); \ + a7 = t7 ^ INW2(6); \ + a8 = t8 ^ INW2(7); \ + a9 = t9 ^ sc->buffer[ptr16][0]; \ + a10 = t10 ^ sc->buffer[ptr16][1]; \ + a11 = t11 ^ sc->buffer[ptr16][2]; \ + a12 = t12 ^ sc->buffer[ptr16][3]; \ + a13 = t13 ^ sc->buffer[ptr16][4]; \ + a14 = t14 ^ sc->buffer[ptr16][5]; \ + a15 = t15 ^ sc->buffer[ptr16][6]; \ + a16 = t16 ^ sc->buffer[ptr16][7]; \ + } while (0) + +#define PANAMA_STEP do { \ + unsigned ptr16, ptr24, ptr31; \ + \ + ptr24 = (ptr0 - 8) & 31; \ + ptr31 = (ptr0 - 1) & 31; \ + BUPDATE; \ + M17(GAMMA); \ + PI_ALL; \ + M17(THETA); \ + ptr16 = ptr0 ^ 16; \ + SIGMA_ALL; \ + ptr0 = ptr31; \ + } while (0) + +/* + * These macros are used to compute + */ +#define INC0 1 +#define INC1 2 +#define INC2 3 +#define INC3 4 +#define INC4 5 +#define INC5 6 +#define INC6 7 +#define INC7 8 + +/* + * Push data by blocks of 32 bytes. "pbuf" must be 32-bit aligned. Each + * iteration processes 32 data bytes; "num" contains the number of + * iterations. + */ +static void +panama_push(sph_panama_context *sc, const unsigned char *pbuf, size_t num) +{ + LVARS + unsigned ptr0; +#if SPH_LITTLE_FAST +#define INW1(i) sph_dec32le_aligned(pbuf + 4 * (i)) +#else + sph_u32 X_var[8]; +#define INW1(i) X_var[i] +#endif +#define INW2(i) INW1(i) + + M17(RSTATE); + ptr0 = sc->buffer_ptr; + while (num -- > 0) { +#if !SPH_LITTLE_FAST + int i; + + for (i = 0; i < 8; i ++) + X_var[i] = sph_dec32le_aligned(pbuf + 4 * (i)); +#endif + PANAMA_STEP; + pbuf = (const unsigned char *)pbuf + 32; + } + M17(WSTATE); + sc->buffer_ptr = ptr0; + +#undef INW1 +#undef INW2 +} + +/* + * Perform the "pull" operation repeatedly ("num" times). The hash output + * will be extracted from the state afterwards. + */ +static void +panama_pull(sph_panama_context *sc, unsigned num) +{ + LVARS + unsigned ptr0; +#define INW1(i) INW_H1(INC ## i) +#define INW_H1(i) INW_H2(i) +#define INW_H2(i) a ## i +#define INW2(i) sc->buffer[ptr4][i] + + M17(RSTATE); + ptr0 = sc->buffer_ptr; + while (num -- > 0) { + unsigned ptr4; + + ptr4 = (ptr0 + 4) & 31; + PANAMA_STEP; + } + M17(WSTATE); + +#undef INW1 +#undef INW_H1 +#undef INW_H2 +#undef INW2 +} + +/* see sph_panama.h */ +void +sph_panama_init(void *cc) +{ + sph_panama_context *sc; + + sc = cc; + /* + * This is not completely conformant, but "it will work + * everywhere". Initial state consists of zeroes everywhere. + * Conceptually, the sph_u32 type may have padding bits which + * must not be set to 0; but such an architecture remains to + * be seen. + */ + sc->data_ptr = 0; + memset(sc->buffer, 0, sizeof sc->buffer); + sc->buffer_ptr = 0; + memset(sc->state, 0, sizeof sc->state); +} + +#ifdef SPH_UPTR +static void +panama_short(void *cc, const void *data, size_t len) +#else +void +sph_panama(void *cc, const void *data, size_t len) +#endif +{ + sph_panama_context *sc; + unsigned current; + + sc = cc; + current = sc->data_ptr; + while (len > 0) { + unsigned clen; + + clen = (sizeof sc->data) - current; + if (clen > len) + clen = len; + memcpy(sc->data + current, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + current += clen; + if (current == sizeof sc->data) { + current = 0; + panama_push(sc, sc->data, 1); + } + } + sc->data_ptr = current; +} + +#ifdef SPH_UPTR +/* see sph_panama.h */ +void +sph_panama(void *cc, const void *data, size_t len) +{ + sph_panama_context *sc; + unsigned current; + size_t rlen; + + if (len < (2 * sizeof sc->data)) { + panama_short(cc, data, len); + return; + } + sc = cc; + current = sc->data_ptr; + if (current > 0) { + unsigned t; + + t = (sizeof sc->data) - current; + panama_short(sc, data, t); + data = (const unsigned char *)data + t; + len -= t; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 3) != 0) { + panama_short(sc, data, len); + return; + } +#endif + panama_push(sc, data, len >> 5); + rlen = len & 31; + if (rlen > 0) + memcpy(sc->data, + (const unsigned char *)data + len - rlen, rlen); + sc->data_ptr = rlen; +} +#endif + +/* see sph_panama.h */ +void +sph_panama_close(void *cc, void *dst) +{ + sph_panama_context *sc; + unsigned current; + int i; + + sc = cc; + current = sc->data_ptr; + sc->data[current ++] = 0x01; + memset(sc->data + current, 0, (sizeof sc->data) - current); + panama_push(sc, sc->data, 1); + panama_pull(sc, 32); + for (i = 0; i < 8; i ++) + sph_enc32le((unsigned char *)dst + 4 * i, sc->state[i + 9]); + sph_panama_init(sc); +} diff --git a/stratum/algos/sph_panama.h b/stratum/algos/sph_panama.h new file mode 100644 index 000000000..763035fb5 --- /dev/null +++ b/stratum/algos/sph_panama.h @@ -0,0 +1,118 @@ +/* $Id: sph_panama.h 154 2010-04-26 17:00:24Z tp $ */ +/** + * PANAMA interface. + * + * PANAMA has been published in: J. Daemen and C. Clapp, "Fast Hashing + * and Stream Encryption with PANAMA", Fast Software Encryption - + * FSE'98, LNCS 1372, Springer (1998), pp. 60--74. + * + * PANAMA is not fully defined with regards to endianness and related + * topics. This implementation follows strict little-endian conventions: + *
    + *
  • Each 32-byte input block is split into eight 32-bit words, the + * first (leftmost) word being numbered 0.
  • + *
  • Each such 32-bit word is decoded from memory in little-endian + * convention.
  • + *
  • The additional padding bit equal to "1" is added by considering + * the least significant bit in a byte to come first; practically, this + * means that a single byte of value 0x01 is appended to the (byte-oriented) + * message, and then 0 to 31 bytes of value 0x00.
  • + *
  • The output consists of eight 32-bit words; the word numbered 0 is + * written first (in leftmost position) and it is encoded in little-endian + * convention. + *
+ * With these conventions, PANAMA is sometimes known as "PANAMA-LE". The + * PANAMA reference implementation uses our conventions for input, but + * prescribes no convention for output. + * + * ==========================(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_panama.h + * @author Thomas Pornin + */ + +#ifndef SPH_PANAMA_H__ +#define SPH_PANAMA_H__ + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for PANAMA. + */ +#define SPH_SIZE_panama 256 + +/** + * This structure is a context for PANAMA computations: it contains the + * intermediate values and some data from the last entered block. Once + * a PANAMA computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running PANAMA computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char data[32]; /* first field, for alignment */ + unsigned data_ptr; + + sph_u32 buffer[32][8]; + unsigned buffer_ptr; + + sph_u32 state[17]; +#endif +} sph_panama_context; + +/** + * Initialize a PANAMA context. This process performs no memory allocation. + * + * @param cc the PANAMA context (pointer to a sph_panama_context) + */ +void sph_panama_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the PANAMA context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_panama(void *cc, const void *data, size_t len); + +/** + * Terminate the current PANAMA computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the PANAMA context + * @param dst the destination buffer + */ +void sph_panama_close(void *cc, void *dst); + +#endif diff --git a/stratum/algos/sph_radiogatun.c b/stratum/algos/sph_radiogatun.c new file mode 100644 index 000000000..708f45c07 --- /dev/null +++ b/stratum/algos/sph_radiogatun.c @@ -0,0 +1,1003 @@ +/* $Id: radiogatun.c 226 2010-06-16 17:28:08Z tp $ */ +/* + * RadioGatun implementation. + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_radiogatun.h" + +#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_RADIOGATUN +#define SPH_SMALL_FOOTPRINT_RADIOGATUN 1 +#endif + +/* ======================================================================= */ +/* + * The core macros. We want to unroll 13 successive rounds so that the + * belt rotation becomes pure routing, solved at compilation time, with + * no unnecessary copying. We also wish all state variables to be + * independant local variables, so that the C compiler becomes free to + * map these on registers at it sees fit. This requires some heavy + * preprocessor trickeries, including a full addition macro modulo 13. + * + * These macros are size-independent. Some macros must be defined before + * use: + * WT evaluates to the type for a word (32-bit or 64-bit) + * T truncates a value to the proper word size + * ROR(x, n) right rotation of a word x, with explicit modular + * reduction of the rotation count n by the word size + * INW(i, j) input word j (0, 1, or 2) of block i (0 to 12) + * + * For INW, the input buffer is pointed to by "buf" which has type + * "const unsigned char *". + */ + +#define MUL19(action) do { \ + action(0); \ + action(1); \ + action(2); \ + action(3); \ + action(4); \ + action(5); \ + action(6); \ + action(7); \ + action(8); \ + action(9); \ + action(10); \ + action(11); \ + action(12); \ + action(13); \ + action(14); \ + action(15); \ + action(16); \ + action(17); \ + action(18); \ + } while (0) + +#define DECL19(b) b ## 0, b ## 1, b ## 2, b ## 3, b ## 4, b ## 5, \ + b ## 6, b ## 7, b ## 8, b ## 9, b ## 10, b ## 11, \ + b ## 12, b ## 13, b ## 14, b ## 15, b ## 16, \ + b ## 17, b ## 18 + +#define M19_T7(i) M19_T7_(i) +#define M19_T7_(i) M19_T7_ ## i +#define M19_T7_0 0 +#define M19_T7_1 7 +#define M19_T7_2 14 +#define M19_T7_3 2 +#define M19_T7_4 9 +#define M19_T7_5 16 +#define M19_T7_6 4 +#define M19_T7_7 11 +#define M19_T7_8 18 +#define M19_T7_9 6 +#define M19_T7_10 13 +#define M19_T7_11 1 +#define M19_T7_12 8 +#define M19_T7_13 15 +#define M19_T7_14 3 +#define M19_T7_15 10 +#define M19_T7_16 17 +#define M19_T7_17 5 +#define M19_T7_18 12 + +#define M19_A1(i) M19_A1_(i) +#define M19_A1_(i) M19_A1_ ## i +#define M19_A1_0 1 +#define M19_A1_1 2 +#define M19_A1_2 3 +#define M19_A1_3 4 +#define M19_A1_4 5 +#define M19_A1_5 6 +#define M19_A1_6 7 +#define M19_A1_7 8 +#define M19_A1_8 9 +#define M19_A1_9 10 +#define M19_A1_10 11 +#define M19_A1_11 12 +#define M19_A1_12 13 +#define M19_A1_13 14 +#define M19_A1_14 15 +#define M19_A1_15 16 +#define M19_A1_16 17 +#define M19_A1_17 18 +#define M19_A1_18 0 + +#define M19_A2(i) M19_A2_(i) +#define M19_A2_(i) M19_A2_ ## i +#define M19_A2_0 2 +#define M19_A2_1 3 +#define M19_A2_2 4 +#define M19_A2_3 5 +#define M19_A2_4 6 +#define M19_A2_5 7 +#define M19_A2_6 8 +#define M19_A2_7 9 +#define M19_A2_8 10 +#define M19_A2_9 11 +#define M19_A2_10 12 +#define M19_A2_11 13 +#define M19_A2_12 14 +#define M19_A2_13 15 +#define M19_A2_14 16 +#define M19_A2_15 17 +#define M19_A2_16 18 +#define M19_A2_17 0 +#define M19_A2_18 1 + +#define M19_A4(i) M19_A4_(i) +#define M19_A4_(i) M19_A4_ ## i +#define M19_A4_0 4 +#define M19_A4_1 5 +#define M19_A4_2 6 +#define M19_A4_3 7 +#define M19_A4_4 8 +#define M19_A4_5 9 +#define M19_A4_6 10 +#define M19_A4_7 11 +#define M19_A4_8 12 +#define M19_A4_9 13 +#define M19_A4_10 14 +#define M19_A4_11 15 +#define M19_A4_12 16 +#define M19_A4_13 17 +#define M19_A4_14 18 +#define M19_A4_15 0 +#define M19_A4_16 1 +#define M19_A4_17 2 +#define M19_A4_18 3 + +#define ACC_a(i) ACC_a_(i) +#define ACC_a_(i) a ## i +#define ACC_atmp(i) ACC_atmp_(i) +#define ACC_atmp_(i) atmp ## i + +#define MILL1(i) (atmp ## i = a ## i ^ T(ACC_a(M19_A1(i)) \ + | ~ACC_a(M19_A2(i)))) +#define MILL2(i) (a ## i = ROR(ACC_atmp(M19_T7(i)), ((i * (i + 1)) >> 1))) +#define MILL3(i) (atmp ## i = a ## i ^ ACC_a(M19_A1(i)) ^ ACC_a(M19_A4(i))) +#define MILL4(i) (a ## i = atmp ## i ^ (i == 0)) + +#define MILL do { \ + WT DECL19(atmp); \ + MUL19(MILL1); \ + MUL19(MILL2); \ + MUL19(MILL3); \ + MUL19(MILL4); \ + } while (0) + +#define DECL13(b) b ## 0 ## _0, b ## 0 ## _1, b ## 0 ## _2, \ + b ## 1 ## _0, b ## 1 ## _1, b ## 1 ## _2, \ + b ## 2 ## _0, b ## 2 ## _1, b ## 2 ## _2, \ + b ## 3 ## _0, b ## 3 ## _1, b ## 3 ## _2, \ + b ## 4 ## _0, b ## 4 ## _1, b ## 4 ## _2, \ + b ## 5 ## _0, b ## 5 ## _1, b ## 5 ## _2, \ + b ## 6 ## _0, b ## 6 ## _1, b ## 6 ## _2, \ + b ## 7 ## _0, b ## 7 ## _1, b ## 7 ## _2, \ + b ## 8 ## _0, b ## 8 ## _1, b ## 8 ## _2, \ + b ## 9 ## _0, b ## 9 ## _1, b ## 9 ## _2, \ + b ## 10 ## _0, b ## 10 ## _1, b ## 10 ## _2, \ + b ## 11 ## _0, b ## 11 ## _1, b ## 11 ## _2, \ + b ## 12 ## _0, b ## 12 ## _1, b ## 12 ## _2 + +#define M13_A(i, j) M13_A_(i, j) +#define M13_A_(i, j) M13_A_ ## i ## _ ## j +#define M13_A_0_0 0 +#define M13_A_0_1 1 +#define M13_A_0_2 2 +#define M13_A_0_3 3 +#define M13_A_0_4 4 +#define M13_A_0_5 5 +#define M13_A_0_6 6 +#define M13_A_0_7 7 +#define M13_A_0_8 8 +#define M13_A_0_9 9 +#define M13_A_0_10 10 +#define M13_A_0_11 11 +#define M13_A_0_12 12 +#define M13_A_1_0 1 +#define M13_A_1_1 2 +#define M13_A_1_2 3 +#define M13_A_1_3 4 +#define M13_A_1_4 5 +#define M13_A_1_5 6 +#define M13_A_1_6 7 +#define M13_A_1_7 8 +#define M13_A_1_8 9 +#define M13_A_1_9 10 +#define M13_A_1_10 11 +#define M13_A_1_11 12 +#define M13_A_1_12 0 +#define M13_A_2_0 2 +#define M13_A_2_1 3 +#define M13_A_2_2 4 +#define M13_A_2_3 5 +#define M13_A_2_4 6 +#define M13_A_2_5 7 +#define M13_A_2_6 8 +#define M13_A_2_7 9 +#define M13_A_2_8 10 +#define M13_A_2_9 11 +#define M13_A_2_10 12 +#define M13_A_2_11 0 +#define M13_A_2_12 1 +#define M13_A_3_0 3 +#define M13_A_3_1 4 +#define M13_A_3_2 5 +#define M13_A_3_3 6 +#define M13_A_3_4 7 +#define M13_A_3_5 8 +#define M13_A_3_6 9 +#define M13_A_3_7 10 +#define M13_A_3_8 11 +#define M13_A_3_9 12 +#define M13_A_3_10 0 +#define M13_A_3_11 1 +#define M13_A_3_12 2 +#define M13_A_4_0 4 +#define M13_A_4_1 5 +#define M13_A_4_2 6 +#define M13_A_4_3 7 +#define M13_A_4_4 8 +#define M13_A_4_5 9 +#define M13_A_4_6 10 +#define M13_A_4_7 11 +#define M13_A_4_8 12 +#define M13_A_4_9 0 +#define M13_A_4_10 1 +#define M13_A_4_11 2 +#define M13_A_4_12 3 +#define M13_A_5_0 5 +#define M13_A_5_1 6 +#define M13_A_5_2 7 +#define M13_A_5_3 8 +#define M13_A_5_4 9 +#define M13_A_5_5 10 +#define M13_A_5_6 11 +#define M13_A_5_7 12 +#define M13_A_5_8 0 +#define M13_A_5_9 1 +#define M13_A_5_10 2 +#define M13_A_5_11 3 +#define M13_A_5_12 4 +#define M13_A_6_0 6 +#define M13_A_6_1 7 +#define M13_A_6_2 8 +#define M13_A_6_3 9 +#define M13_A_6_4 10 +#define M13_A_6_5 11 +#define M13_A_6_6 12 +#define M13_A_6_7 0 +#define M13_A_6_8 1 +#define M13_A_6_9 2 +#define M13_A_6_10 3 +#define M13_A_6_11 4 +#define M13_A_6_12 5 +#define M13_A_7_0 7 +#define M13_A_7_1 8 +#define M13_A_7_2 9 +#define M13_A_7_3 10 +#define M13_A_7_4 11 +#define M13_A_7_5 12 +#define M13_A_7_6 0 +#define M13_A_7_7 1 +#define M13_A_7_8 2 +#define M13_A_7_9 3 +#define M13_A_7_10 4 +#define M13_A_7_11 5 +#define M13_A_7_12 6 +#define M13_A_8_0 8 +#define M13_A_8_1 9 +#define M13_A_8_2 10 +#define M13_A_8_3 11 +#define M13_A_8_4 12 +#define M13_A_8_5 0 +#define M13_A_8_6 1 +#define M13_A_8_7 2 +#define M13_A_8_8 3 +#define M13_A_8_9 4 +#define M13_A_8_10 5 +#define M13_A_8_11 6 +#define M13_A_8_12 7 +#define M13_A_9_0 9 +#define M13_A_9_1 10 +#define M13_A_9_2 11 +#define M13_A_9_3 12 +#define M13_A_9_4 0 +#define M13_A_9_5 1 +#define M13_A_9_6 2 +#define M13_A_9_7 3 +#define M13_A_9_8 4 +#define M13_A_9_9 5 +#define M13_A_9_10 6 +#define M13_A_9_11 7 +#define M13_A_9_12 8 +#define M13_A_10_0 10 +#define M13_A_10_1 11 +#define M13_A_10_2 12 +#define M13_A_10_3 0 +#define M13_A_10_4 1 +#define M13_A_10_5 2 +#define M13_A_10_6 3 +#define M13_A_10_7 4 +#define M13_A_10_8 5 +#define M13_A_10_9 6 +#define M13_A_10_10 7 +#define M13_A_10_11 8 +#define M13_A_10_12 9 +#define M13_A_11_0 11 +#define M13_A_11_1 12 +#define M13_A_11_2 0 +#define M13_A_11_3 1 +#define M13_A_11_4 2 +#define M13_A_11_5 3 +#define M13_A_11_6 4 +#define M13_A_11_7 5 +#define M13_A_11_8 6 +#define M13_A_11_9 7 +#define M13_A_11_10 8 +#define M13_A_11_11 9 +#define M13_A_11_12 10 +#define M13_A_12_0 12 +#define M13_A_12_1 0 +#define M13_A_12_2 1 +#define M13_A_12_3 2 +#define M13_A_12_4 3 +#define M13_A_12_5 4 +#define M13_A_12_6 5 +#define M13_A_12_7 6 +#define M13_A_12_8 7 +#define M13_A_12_9 8 +#define M13_A_12_10 9 +#define M13_A_12_11 10 +#define M13_A_12_12 11 + +#define M13_N(i) M13_N_(i) +#define M13_N_(i) M13_N_ ## i +#define M13_N_0 12 +#define M13_N_1 11 +#define M13_N_2 10 +#define M13_N_3 9 +#define M13_N_4 8 +#define M13_N_5 7 +#define M13_N_6 6 +#define M13_N_7 5 +#define M13_N_8 4 +#define M13_N_9 3 +#define M13_N_10 2 +#define M13_N_11 1 +#define M13_N_12 0 + +#define ACC_b(i, k) ACC_b_(i, k) +#define ACC_b_(i, k) b ## i ## _ ## k + +#define ROUND_ELT(k, s) do { \ + if ((bj += 3) == 39) \ + bj = 0; \ + sc->b[bj + s] ^= a ## k; \ + } while (0) + +#define ROUND_SF(j) do { \ + size_t bj = (j) * 3; \ + ROUND_ELT(1, 0); \ + ROUND_ELT(2, 1); \ + ROUND_ELT(3, 2); \ + ROUND_ELT(4, 0); \ + ROUND_ELT(5, 1); \ + ROUND_ELT(6, 2); \ + ROUND_ELT(7, 0); \ + ROUND_ELT(8, 1); \ + ROUND_ELT(9, 2); \ + ROUND_ELT(10, 0); \ + ROUND_ELT(11, 1); \ + ROUND_ELT(12, 2); \ + MILL; \ + bj = (j) * 3; \ + a ## 13 ^= sc->b[bj + 0]; \ + a ## 14 ^= sc->b[bj + 1]; \ + a ## 15 ^= sc->b[bj + 2]; \ + } while (0) + +#define INPUT_SF(j, p0, p1, p2) do { \ + size_t bj = ((j) + 1) * 3; \ + if (bj == 39) \ + bj = 0; \ + sc->b[bj + 0] ^= (p0); \ + sc->b[bj + 1] ^= (p1); \ + sc->b[bj + 2] ^= (p2); \ + a16 ^= (p0); \ + a17 ^= (p1); \ + a18 ^= (p2); \ + } while (0) + + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN + +#define ROUND ROUND_SF +#define INPUT INPUT_SF + +#else + +/* + * Round function R, on base j. The value j is such that B[0] is actually + * b[j] after the initial rotation. On the 13-round macro, j has the + * successive values 12, 11, 10... 1, 0. + */ +#define ROUND(j) do { \ + ACC_b(M13_A(1, j), 0) ^= a ## 1; \ + ACC_b(M13_A(2, j), 1) ^= a ## 2; \ + ACC_b(M13_A(3, j), 2) ^= a ## 3; \ + ACC_b(M13_A(4, j), 0) ^= a ## 4; \ + ACC_b(M13_A(5, j), 1) ^= a ## 5; \ + ACC_b(M13_A(6, j), 2) ^= a ## 6; \ + ACC_b(M13_A(7, j), 0) ^= a ## 7; \ + ACC_b(M13_A(8, j), 1) ^= a ## 8; \ + ACC_b(M13_A(9, j), 2) ^= a ## 9; \ + ACC_b(M13_A(10, j), 0) ^= a ## 10; \ + ACC_b(M13_A(11, j), 1) ^= a ## 11; \ + ACC_b(M13_A(12, j), 2) ^= a ## 12; \ + MILL; \ + a ## 13 ^= ACC_b(j, 0); \ + a ## 14 ^= ACC_b(j, 1); \ + a ## 15 ^= ACC_b(j, 2); \ + } while (0) + +#define INPUT(j, p0, p1, p2) do { \ + ACC_b(M13_A(1, j), 0) ^= (p0); \ + ACC_b(M13_A(1, j), 1) ^= (p1); \ + ACC_b(M13_A(1, j), 2) ^= (p2); \ + a16 ^= (p0); \ + a17 ^= (p1); \ + a18 ^= (p2); \ + } while (0) + +#endif + +#define MUL13(action) do { \ + action(0); \ + action(1); \ + action(2); \ + action(3); \ + action(4); \ + action(5); \ + action(6); \ + action(7); \ + action(8); \ + action(9); \ + action(10); \ + action(11); \ + action(12); \ + } while (0) + +#define MILL_READ_ELT(i) do { \ + a ## i = sc->a[i]; \ + } while (0) + +#define MILL_WRITE_ELT(i) do { \ + sc->a[i] = a ## i; \ + } while (0) + +#define STATE_READ_SF do { \ + MUL19(MILL_READ_ELT); \ + } while (0) + +#define STATE_WRITE_SF do { \ + MUL19(MILL_WRITE_ELT); \ + } while (0) + +#define PUSH13_SF do { \ + WT DECL19(a); \ + const unsigned char *buf; \ + \ + buf = data; \ + STATE_READ_SF; \ + while (len >= sizeof sc->data) { \ + size_t mk; \ + for (mk = 13; mk > 0; mk --) { \ + WT p0 = INW(0, 0); \ + WT p1 = INW(0, 1); \ + WT p2 = INW(0, 2); \ + INPUT_SF(mk - 1, p0, p1, p2); \ + ROUND_SF(mk - 1); \ + buf += (sizeof sc->data) / 13; \ + len -= (sizeof sc->data) / 13; \ + } \ + } \ + STATE_WRITE_SF; \ + return len; \ + } while (0) + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN + +#define STATE_READ STATE_READ_SF +#define STATE_WRITE STATE_WRITE_SF +#define PUSH13 PUSH13_SF + +#else + +#define BELT_READ_ELT(i) do { \ + b ## i ## _0 = sc->b[3 * i + 0]; \ + b ## i ## _1 = sc->b[3 * i + 1]; \ + b ## i ## _2 = sc->b[3 * i + 2]; \ + } while (0) + +#define BELT_WRITE_ELT(i) do { \ + sc->b[3 * i + 0] = b ## i ## _0; \ + sc->b[3 * i + 1] = b ## i ## _1; \ + sc->b[3 * i + 2] = b ## i ## _2; \ + } while (0) + +#define STATE_READ do { \ + MUL13(BELT_READ_ELT); \ + MUL19(MILL_READ_ELT); \ + } while (0) + +#define STATE_WRITE do { \ + MUL13(BELT_WRITE_ELT); \ + MUL19(MILL_WRITE_ELT); \ + } while (0) + +/* + * Input data by chunks of 13*3 blocks. This is the body of the + * radiogatun32_push13() and radiogatun64_push13() functions. + */ +#define PUSH13 do { \ + WT DECL19(a), DECL13(b); \ + const unsigned char *buf; \ + \ + buf = data; \ + STATE_READ; \ + while (len >= sizeof sc->data) { \ + WT p0, p1, p2; \ + MUL13(PUSH13_ELT); \ + buf += sizeof sc->data; \ + len -= sizeof sc->data; \ + } \ + STATE_WRITE; \ + return len; \ + } while (0) + +#define PUSH13_ELT(k) do { \ + p0 = INW(k, 0); \ + p1 = INW(k, 1); \ + p2 = INW(k, 2); \ + INPUT(M13_N(k), p0, p1, p2); \ + ROUND(M13_N(k)); \ + } while (0) + +#endif + +#define BLANK13_SF do { \ + size_t mk = 13; \ + while (mk -- > 0) \ + ROUND_SF(mk); \ + } while (0) + +#define BLANK1_SF do { \ + WT tmp0, tmp1, tmp2; \ + ROUND_SF(12); \ + tmp0 = sc->b[36]; \ + tmp1 = sc->b[37]; \ + tmp2 = sc->b[38]; \ + memmove(sc->b + 3, sc->b, 36 * sizeof sc->b[0]); \ + sc->b[0] = tmp0; \ + sc->b[1] = tmp1; \ + sc->b[2] = tmp2; \ + } while (0) + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN + +#define BLANK13 BLANK13_SF +#define BLANK1 BLANK1_SF + +#else + +/* + * Run 13 blank rounds. This macro expects the "a" and "b" state variables + * to be alread declared. + */ +#define BLANK13 MUL13(BLANK13_ELT) + +#define BLANK13_ELT(k) ROUND(M13_N(k)) + +#define MUL12(action) do { \ + action(0); \ + action(1); \ + action(2); \ + action(3); \ + action(4); \ + action(5); \ + action(6); \ + action(7); \ + action(8); \ + action(9); \ + action(10); \ + action(11); \ + } while (0) + +/* + * Run a single blank round, and physically rotate the belt. This is used + * for the last blank rounds, and the output rounds. This macro expects the + * "a" abd "b" state variables to be already declared. + */ +#define BLANK1 do { \ + WT tmp0, tmp1, tmp2; \ + ROUND(12); \ + tmp0 = b0_0; \ + tmp1 = b0_1; \ + tmp2 = b0_2; \ + MUL12(BLANK1_ELT); \ + b1_0 = tmp0; \ + b1_1 = tmp1; \ + b1_2 = tmp2; \ + } while (0) + +#define BLANK1_ELT(i) do { \ + ACC_b(M13_A(M13_N(i), 1), 0) = ACC_b(M13_N(i), 0); \ + ACC_b(M13_A(M13_N(i), 1), 1) = ACC_b(M13_N(i), 1); \ + ACC_b(M13_A(M13_N(i), 1), 2) = ACC_b(M13_N(i), 2); \ + } while (0) + +#endif + +#define NO_TOKEN + +/* + * Perform padding, then blank rounds, then output some words. This is + * the body of sph_radiogatun32_close() and sph_radiogatun64_close(). + */ +#define CLOSE_SF(width) CLOSE_GEN(width, \ + NO_TOKEN, STATE_READ_SF, BLANK1_SF, BLANK13_SF) + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN +#define CLOSE CLOSE_SF +#else +#define CLOSE(width) CLOSE_GEN(width, \ + WT DECL13(b);, STATE_READ, BLANK1, BLANK13) +#endif + +#define CLOSE_GEN(width, WTb13, state_read, blank1, blank13) do { \ + unsigned ptr, num; \ + unsigned char *out; \ + WT DECL19(a); \ + WTb13 \ + \ + ptr = sc->data_ptr; \ + sc->data[ptr ++] = 0x01; \ + memset(sc->data + ptr, 0, (sizeof sc->data) - ptr); \ + radiogatun ## width ## _push13(sc, sc->data, sizeof sc->data); \ + \ + num = 17; \ + for (;;) { \ + ptr += 3 * (width >> 3); \ + if (ptr > sizeof sc->data) \ + break; \ + num --; \ + } \ + \ + state_read; \ + if (num >= 13) { \ + blank13; \ + num -= 13; \ + } \ + while (num -- > 0) \ + blank1; \ + \ + num = 0; \ + out = dst; \ + for (;;) { \ + OUTW(out, a1); \ + out += width >> 3; \ + OUTW(out, a2); \ + out += width >> 3; \ + num += 2 * (width >> 3); \ + if (num >= 32) \ + break; \ + blank1; \ + } \ + INIT; \ + } while (0) + +/* + * Initialize context structure. + */ +#if SPH_LITTLE_ENDIAN || SPH_BIG_ENDIAN + +#define INIT do { \ + memset(sc->a, 0, sizeof sc->a); \ + memset(sc->b, 0, sizeof sc->b); \ + sc->data_ptr = 0; \ + } while (0) + +#else + +#define INIT do { \ + size_t u; \ + for (u = 0; u < 19; u ++) \ + sc->a[u] = 0; \ + for (u = 0; u < 39; u ++) \ + sc->b[u] = 0; \ + sc->data_ptr = 0; \ + } while (0) + +#endif + +/* ======================================================================= */ +/* + * RadioGatun[32]. + */ + +#if !SPH_NO_RG32 + +#undef WT +#define WT sph_u32 +#undef T +#define T SPH_T32 +#undef ROR +#define ROR(x, n) SPH_T32(((x) << ((32 - (n)) & 31)) | ((x) >> ((n) & 31))) +#undef INW +#define INW(i, j) sph_dec32le_aligned(buf + (4 * (3 * (i) + (j)))) +#undef OUTW +#define OUTW(b, v) sph_enc32le(b, v) + +/* + * Insert data by big chunks of 13*12 = 156 bytes. Returned value is the + * number of remaining bytes (between 0 and 155). This method assumes that + * the input data is suitably aligned. + */ +static size_t +radiogatun32_push13(sph_radiogatun32_context *sc, const void *data, size_t len) +{ + PUSH13; +} + +/* see sph_radiogatun.h */ +void +sph_radiogatun32_init(void *cc) +{ + sph_radiogatun32_context *sc; + + sc = cc; + INIT; +} + +#ifdef SPH_UPTR +static void +radiogatun32_short(void *cc, const void *data, size_t len) +#else +/* see sph_radiogatun.h */ +void +sph_radiogatun32(void *cc, const void *data, size_t len) +#endif +{ + sph_radiogatun32_context *sc; + unsigned ptr; + + sc = cc; + ptr = sc->data_ptr; + while (len > 0) { + size_t clen; + + clen = (sizeof sc->data) - ptr; + if (clen > len) + clen = len; + memcpy(sc->data + ptr, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + ptr += clen; + if (ptr == sizeof sc->data) { + radiogatun32_push13(sc, sc->data, sizeof sc->data); + ptr = 0; + } + } + sc->data_ptr = ptr; +} + +#ifdef SPH_UPTR +/* see sph_radiogatun.h */ +void +sph_radiogatun32(void *cc, const void *data, size_t len) +{ + sph_radiogatun32_context *sc; + unsigned ptr; + size_t rlen; + + if (len < (2 * sizeof sc->data)) { + radiogatun32_short(cc, data, len); + return; + } + sc = cc; + ptr = sc->data_ptr; + if (ptr > 0) { + unsigned t; + + t = (sizeof sc->data) - ptr; + radiogatun32_short(sc, data, t); + data = (const unsigned char *)data + t; + len -= t; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 3) != 0) { + radiogatun32_short(sc, data, len); + return; + } +#endif + rlen = radiogatun32_push13(sc, data, len); + memcpy(sc->data, (const unsigned char *)data + len - rlen, rlen); + sc->data_ptr = rlen; +} +#endif + +/* see sph_radiogatun.h */ +void +sph_radiogatun32_close(void *cc, void *dst) +{ + sph_radiogatun32_context *sc; + + sc = cc; + CLOSE(32); +} + +#endif + +/* ======================================================================= */ +/* + * RadioGatun[64]. Compiled only if a 64-bit or more type is available. + */ + +#if SPH_64 + +#if !SPH_NO_RG64 + +#undef WT +#define WT sph_u64 +#undef T +#define T SPH_T64 +#undef ROR +#define ROR(x, n) SPH_T64(((x) << ((64 - (n)) & 63)) | ((x) >> ((n) & 63))) +#undef INW +#define INW(i, j) sph_dec64le_aligned(buf + (8 * (3 * (i) + (j)))) +#undef OUTW +#define OUTW(b, v) sph_enc64le(b, v) + +/* + * On 32-bit x86, register pressure is such that using the small + * footprint version is a net gain (x2 speed), because that variant + * uses fewer local variables. + */ +#if SPH_I386_MSVC || SPH_I386_GCC || defined __i386__ +#undef PUSH13 +#define PUSH13 PUSH13_SF +#undef CLOSE +#define CLOSE CLOSE_SF +#endif + +/* + * Insert data by big chunks of 13*24 = 312 bytes. Returned value is the + * number of remaining bytes (between 0 and 311). This method assumes that + * the input data is suitably aligned. + */ +static size_t +radiogatun64_push13(sph_radiogatun64_context *sc, const void *data, size_t len) +{ + PUSH13; +} + +/* see sph_radiogatun.h */ +void +sph_radiogatun64_init(void *cc) +{ + sph_radiogatun64_context *sc; + + sc = cc; + INIT; +} + +#ifdef SPH_UPTR +static void +radiogatun64_short(void *cc, const void *data, size_t len) +#else +/* see sph_radiogatun.h */ +void +sph_radiogatun64(void *cc, const void *data, size_t len) +#endif +{ + sph_radiogatun64_context *sc; + unsigned ptr; + + sc = cc; + ptr = sc->data_ptr; + while (len > 0) { + size_t clen; + + clen = (sizeof sc->data) - ptr; + if (clen > len) + clen = len; + memcpy(sc->data + ptr, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + ptr += clen; + if (ptr == sizeof sc->data) { + radiogatun64_push13(sc, sc->data, sizeof sc->data); + ptr = 0; + } + } + sc->data_ptr = ptr; +} + +#ifdef SPH_UPTR +/* see sph_radiogatun.h */ +void +sph_radiogatun64(void *cc, const void *data, size_t len) +{ + sph_radiogatun64_context *sc; + unsigned ptr; + size_t rlen; + + if (len < (2 * sizeof sc->data)) { + radiogatun64_short(cc, data, len); + return; + } + sc = cc; + ptr = sc->data_ptr; + if (ptr > 0) { + unsigned t; + + t = (sizeof sc->data) - ptr; + radiogatun64_short(sc, data, t); + data = (const unsigned char *)data + t; + len -= t; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 7) != 0) { + radiogatun64_short(sc, data, len); + return; + } +#endif + rlen = radiogatun64_push13(sc, data, len); + memcpy(sc->data, (const unsigned char *)data + len - rlen, rlen); + sc->data_ptr = rlen; +} +#endif + +/* see sph_radiogatun.h */ +void +sph_radiogatun64_close(void *cc, void *dst) +{ + sph_radiogatun64_context *sc; + + sc = cc; + CLOSE(64); +} + +#endif + +#endif diff --git a/stratum/algos/sph_radiogatun.h b/stratum/algos/sph_radiogatun.h new file mode 100644 index 000000000..f8cedc233 --- /dev/null +++ b/stratum/algos/sph_radiogatun.h @@ -0,0 +1,186 @@ +/* $Id: sph_radiogatun.h 226 2010-06-16 17:28:08Z tp $ */ +/** + * RadioGatun interface. + * + * RadioGatun has been published in: G. Bertoni, J. Daemen, M. Peeters + * and G. Van Assche, "RadioGatun, a belt-and-mill hash function", + * presented at the Second Cryptographic Hash Workshop, Santa Barbara, + * August 24-25, 2006. The main Web site, containing that article, the + * reference code and some test vectors, appears to be currently located + * at the following URL: http://radiogatun.noekeon.org/ + * + * The presentation article does not specify endianness or padding. The + * reference code uses the following conventions, which we also apply + * here: + *
    + *
  • The input message is an integral number of sequences of three + * words. Each word is either a 32-bit of 64-bit word (depending on + * the version of RadioGatun).
  • + *
  • Input bytes are decoded into words using little-endian + * convention.
  • + *
  • Padding consists of a single bit of value 1, using little-endian + * convention within bytes (i.e. for a byte-oriented input, a single + * byte of value 0x01 is appended), then enough bits of value 0 to finish + * the current block.
  • + *
  • Output consists of 256 bits. Successive output words are encoded + * with little-endian convention.
  • + *
+ * These conventions are very close to those we use for PANAMA, which is + * a close ancestor or RadioGatun. + * + * RadioGatun is actually a family of functions, depending on some + * internal parameters. We implement here two functions, with a "belt + * length" of 13, a "belt width" of 3, and a "mill length" of 19. The + * RadioGatun[32] version uses 32-bit words, while the RadioGatun[64] + * variant uses 64-bit words. + * + * Strictly speaking, the name "RadioGatun" should use an acute accent + * on the "u", which we omitted here to keep strict ASCII-compatibility + * of this file. + * + * ==========================(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_radiogatun.h + * @author Thomas Pornin + */ + +#ifndef SPH_RADIOGATUN_H__ +#define SPH_RADIOGATUN_H__ + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for RadioGatun[32]. + */ +#define SPH_SIZE_radiogatun32 256 + +/** + * This structure is a context for RadioGatun[32] computations: it + * contains intermediate values and some data from the last entered + * block. Once a RadioGatun[32] computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running RadioGatun[32] + * computation can be cloned by copying the context (e.g. with a + * simple memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char data[156]; /* first field, for alignment */ + unsigned data_ptr; + sph_u32 a[19], b[39]; +#endif +} sph_radiogatun32_context; + +/** + * Initialize a RadioGatun[32] context. This process performs no + * memory allocation. + * + * @param cc the RadioGatun[32] context (pointer to a + * sph_radiogatun32_context) + */ +void sph_radiogatun32_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the RadioGatun[32] context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_radiogatun32(void *cc, const void *data, size_t len); + +/** + * Terminate the current RadioGatun[32] computation and output the + * result into the provided buffer. The destination buffer must be wide + * enough to accomodate the result (32 bytes). The context is + * automatically reinitialized. + * + * @param cc the RadioGatun[32] context + * @param dst the destination buffer + */ +void sph_radiogatun32_close(void *cc, void *dst); + +#if SPH_64 + +/** + * Output size (in bits) for RadioGatun[64]. + */ +#define SPH_SIZE_radiogatun64 256 + +/** + * This structure is a context for RadioGatun[64] computations: it + * contains intermediate values and some data from the last entered + * block. Once a RadioGatun[64] computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running RadioGatun[64] + * computation can be cloned by copying the context (e.g. with a + * simple memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char data[312]; /* first field, for alignment */ + unsigned data_ptr; + sph_u64 a[19], b[39]; +#endif +} sph_radiogatun64_context; + +/** + * Initialize a RadioGatun[64] context. This process performs no + * memory allocation. + * + * @param cc the RadioGatun[64] context (pointer to a + * sph_radiogatun64_context) + */ +void sph_radiogatun64_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the RadioGatun[64] context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_radiogatun64(void *cc, const void *data, size_t len); + +/** + * Terminate the current RadioGatun[64] computation and output the + * result into the provided buffer. The destination buffer must be wide + * enough to accomodate the result (32 bytes). The context is + * automatically reinitialized. + * + * @param cc the RadioGatun[64] context + * @param dst the destination buffer + */ +void sph_radiogatun64_close(void *cc, void *dst); + +#endif + +#endif \ No newline at end of file diff --git a/stratum/algos/sph_sha2.c b/stratum/algos/sph_sha2.c new file mode 100644 index 000000000..aab2c5518 --- /dev/null +++ b/stratum/algos/sph_sha2.c @@ -0,0 +1,691 @@ +/* $Id: sha2.c 227 2010-06-16 17:28:38Z tp $ */ +/* + * SHA-224 / SHA-256 implementation. + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_sha2.h" + +#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_SHA2 +#define SPH_SMALL_FOOTPRINT_SHA2 1 +#endif + +#define CH(X, Y, Z) ((((Y) ^ (Z)) & (X)) ^ (Z)) +#define MAJ(X, Y, Z) (((Y) & (Z)) | (((Y) | (Z)) & (X))) + +#define ROTR SPH_ROTR32 + +#define BSG2_0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22)) +#define BSG2_1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25)) +#define SSG2_0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SPH_T32((x) >> 3)) +#define SSG2_1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SPH_T32((x) >> 10)) + +static const sph_u32 H224[8] = { + SPH_C32(0xC1059ED8), SPH_C32(0x367CD507), SPH_C32(0x3070DD17), + SPH_C32(0xF70E5939), SPH_C32(0xFFC00B31), SPH_C32(0x68581511), + SPH_C32(0x64F98FA7), SPH_C32(0xBEFA4FA4) +}; + +static const sph_u32 H256[8] = { + SPH_C32(0x6A09E667), SPH_C32(0xBB67AE85), SPH_C32(0x3C6EF372), + SPH_C32(0xA54FF53A), SPH_C32(0x510E527F), SPH_C32(0x9B05688C), + SPH_C32(0x1F83D9AB), SPH_C32(0x5BE0CD19) +}; + +/* + * The SHA2_ROUND_BODY defines the body for a SHA-224 / SHA-256 + * compression function implementation. The "in" parameter should + * evaluate, when applied to a numerical input parameter from 0 to 15, + * to an expression which yields the corresponding input block. The "r" + * parameter should evaluate to an array or pointer expression + * designating the array of 8 words which contains the input and output + * of the compression function. + */ + +#if SPH_SMALL_FOOTPRINT_SHA2 + +static const sph_u32 K[64] = { + SPH_C32(0x428A2F98), SPH_C32(0x71374491), + SPH_C32(0xB5C0FBCF), SPH_C32(0xE9B5DBA5), + SPH_C32(0x3956C25B), SPH_C32(0x59F111F1), + SPH_C32(0x923F82A4), SPH_C32(0xAB1C5ED5), + SPH_C32(0xD807AA98), SPH_C32(0x12835B01), + SPH_C32(0x243185BE), SPH_C32(0x550C7DC3), + SPH_C32(0x72BE5D74), SPH_C32(0x80DEB1FE), + SPH_C32(0x9BDC06A7), SPH_C32(0xC19BF174), + SPH_C32(0xE49B69C1), SPH_C32(0xEFBE4786), + SPH_C32(0x0FC19DC6), SPH_C32(0x240CA1CC), + SPH_C32(0x2DE92C6F), SPH_C32(0x4A7484AA), + SPH_C32(0x5CB0A9DC), SPH_C32(0x76F988DA), + SPH_C32(0x983E5152), SPH_C32(0xA831C66D), + SPH_C32(0xB00327C8), SPH_C32(0xBF597FC7), + SPH_C32(0xC6E00BF3), SPH_C32(0xD5A79147), + SPH_C32(0x06CA6351), SPH_C32(0x14292967), + SPH_C32(0x27B70A85), SPH_C32(0x2E1B2138), + SPH_C32(0x4D2C6DFC), SPH_C32(0x53380D13), + SPH_C32(0x650A7354), SPH_C32(0x766A0ABB), + SPH_C32(0x81C2C92E), SPH_C32(0x92722C85), + SPH_C32(0xA2BFE8A1), SPH_C32(0xA81A664B), + SPH_C32(0xC24B8B70), SPH_C32(0xC76C51A3), + SPH_C32(0xD192E819), SPH_C32(0xD6990624), + SPH_C32(0xF40E3585), SPH_C32(0x106AA070), + SPH_C32(0x19A4C116), SPH_C32(0x1E376C08), + SPH_C32(0x2748774C), SPH_C32(0x34B0BCB5), + SPH_C32(0x391C0CB3), SPH_C32(0x4ED8AA4A), + SPH_C32(0x5B9CCA4F), SPH_C32(0x682E6FF3), + SPH_C32(0x748F82EE), SPH_C32(0x78A5636F), + SPH_C32(0x84C87814), SPH_C32(0x8CC70208), + SPH_C32(0x90BEFFFA), SPH_C32(0xA4506CEB), + SPH_C32(0xBEF9A3F7), SPH_C32(0xC67178F2) +}; + +#define SHA2_MEXP1(in, pc) do { \ + W[pc] = in(pc); \ + } while (0) + +#define SHA2_MEXP2(in, pc) do { \ + W[(pc) & 0x0F] = SPH_T32(SSG2_1(W[((pc) - 2) & 0x0F]) \ + + W[((pc) - 7) & 0x0F] \ + + SSG2_0(W[((pc) - 15) & 0x0F]) + W[(pc) & 0x0F]); \ + } while (0) + +#define SHA2_STEPn(n, a, b, c, d, e, f, g, h, in, pc) do { \ + sph_u32 t1, t2; \ + SHA2_MEXP ## n(in, pc); \ + t1 = SPH_T32(h + BSG2_1(e) + CH(e, f, g) \ + + K[pcount + (pc)] + W[(pc) & 0x0F]); \ + t2 = SPH_T32(BSG2_0(a) + MAJ(a, b, c)); \ + d = SPH_T32(d + t1); \ + h = SPH_T32(t1 + t2); \ + } while (0) + +#define SHA2_STEP1(a, b, c, d, e, f, g, h, in, pc) \ + SHA2_STEPn(1, a, b, c, d, e, f, g, h, in, pc) +#define SHA2_STEP2(a, b, c, d, e, f, g, h, in, pc) \ + SHA2_STEPn(2, a, b, c, d, e, f, g, h, in, pc) + +#define SHA2_ROUND_BODY(in, r) do { \ + sph_u32 A, B, C, D, E, F, G, H; \ + sph_u32 W[16]; \ + unsigned pcount; \ + \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + D = (r)[3]; \ + E = (r)[4]; \ + F = (r)[5]; \ + G = (r)[6]; \ + H = (r)[7]; \ + pcount = 0; \ + SHA2_STEP1(A, B, C, D, E, F, G, H, in, 0); \ + SHA2_STEP1(H, A, B, C, D, E, F, G, in, 1); \ + SHA2_STEP1(G, H, A, B, C, D, E, F, in, 2); \ + SHA2_STEP1(F, G, H, A, B, C, D, E, in, 3); \ + SHA2_STEP1(E, F, G, H, A, B, C, D, in, 4); \ + SHA2_STEP1(D, E, F, G, H, A, B, C, in, 5); \ + SHA2_STEP1(C, D, E, F, G, H, A, B, in, 6); \ + SHA2_STEP1(B, C, D, E, F, G, H, A, in, 7); \ + SHA2_STEP1(A, B, C, D, E, F, G, H, in, 8); \ + SHA2_STEP1(H, A, B, C, D, E, F, G, in, 9); \ + SHA2_STEP1(G, H, A, B, C, D, E, F, in, 10); \ + SHA2_STEP1(F, G, H, A, B, C, D, E, in, 11); \ + SHA2_STEP1(E, F, G, H, A, B, C, D, in, 12); \ + SHA2_STEP1(D, E, F, G, H, A, B, C, in, 13); \ + SHA2_STEP1(C, D, E, F, G, H, A, B, in, 14); \ + SHA2_STEP1(B, C, D, E, F, G, H, A, in, 15); \ + for (pcount = 16; pcount < 64; pcount += 16) { \ + SHA2_STEP2(A, B, C, D, E, F, G, H, in, 0); \ + SHA2_STEP2(H, A, B, C, D, E, F, G, in, 1); \ + SHA2_STEP2(G, H, A, B, C, D, E, F, in, 2); \ + SHA2_STEP2(F, G, H, A, B, C, D, E, in, 3); \ + SHA2_STEP2(E, F, G, H, A, B, C, D, in, 4); \ + SHA2_STEP2(D, E, F, G, H, A, B, C, in, 5); \ + SHA2_STEP2(C, D, E, F, G, H, A, B, in, 6); \ + SHA2_STEP2(B, C, D, E, F, G, H, A, in, 7); \ + SHA2_STEP2(A, B, C, D, E, F, G, H, in, 8); \ + SHA2_STEP2(H, A, B, C, D, E, F, G, in, 9); \ + SHA2_STEP2(G, H, A, B, C, D, E, F, in, 10); \ + SHA2_STEP2(F, G, H, A, B, C, D, E, in, 11); \ + SHA2_STEP2(E, F, G, H, A, B, C, D, in, 12); \ + SHA2_STEP2(D, E, F, G, H, A, B, C, in, 13); \ + SHA2_STEP2(C, D, E, F, G, H, A, B, in, 14); \ + SHA2_STEP2(B, C, D, E, F, G, H, A, in, 15); \ + } \ + (r)[0] = SPH_T32((r)[0] + A); \ + (r)[1] = SPH_T32((r)[1] + B); \ + (r)[2] = SPH_T32((r)[2] + C); \ + (r)[3] = SPH_T32((r)[3] + D); \ + (r)[4] = SPH_T32((r)[4] + E); \ + (r)[5] = SPH_T32((r)[5] + F); \ + (r)[6] = SPH_T32((r)[6] + G); \ + (r)[7] = SPH_T32((r)[7] + H); \ + } while (0) + +#else + +#define SHA2_ROUND_BODY(in, r) do { \ + sph_u32 A, B, C, D, E, F, G, H, T1, T2; \ + sph_u32 W00, W01, W02, W03, W04, W05, W06, W07; \ + sph_u32 W08, W09, W10, W11, W12, W13, W14, W15; \ + int i; \ + \ + A = (r)[0]; \ + B = (r)[1]; \ + C = (r)[2]; \ + D = (r)[3]; \ + E = (r)[4]; \ + F = (r)[5]; \ + G = (r)[6]; \ + H = (r)[7]; \ + W00 = in(0); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x428A2F98) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = in(1); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x71374491) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = in(2); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0xB5C0FBCF) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = in(3); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0xE9B5DBA5) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = in(4); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x3956C25B) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = in(5); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x59F111F1) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = in(6); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x923F82A4) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = in(7); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0xAB1C5ED5) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = in(8); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0xD807AA98) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = in(9); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x12835B01) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = in(10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x243185BE) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = in(11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x550C7DC3) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = in(12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x72BE5D74) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = in(13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x80DEB1FE) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = in(14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x9BDC06A7) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = in(15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0xC19BF174) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0xE49B69C1) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0xEFBE4786) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x0FC19DC6) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x240CA1CC) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x2DE92C6F) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x4A7484AA) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x5CB0A9DC) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x76F988DA) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x983E5152) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0xA831C66D) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0xB00327C8) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0xBF597FC7) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0xC6E00BF3) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0xD5A79147) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x06CA6351) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x14292967) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x27B70A85) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x2E1B2138) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x4D2C6DFC) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x53380D13) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x650A7354) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x766A0ABB) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x81C2C92E) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x92722C85) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0xA2BFE8A1) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0xA81A664B) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0xC24B8B70) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0xC76C51A3) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0xD192E819) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0xD6990624) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0xF40E3585) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x106AA070) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W00 = SPH_T32(SSG2_1(W14) + W09 + SSG2_0(W01) + W00); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x19A4C116) + W00); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W01 = SPH_T32(SSG2_1(W15) + W10 + SSG2_0(W02) + W01); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x1E376C08) + W01); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W02 = SPH_T32(SSG2_1(W00) + W11 + SSG2_0(W03) + W02); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x2748774C) + W02); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W03 = SPH_T32(SSG2_1(W01) + W12 + SSG2_0(W04) + W03); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x34B0BCB5) + W03); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W04 = SPH_T32(SSG2_1(W02) + W13 + SSG2_0(W05) + W04); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x391C0CB3) + W04); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W05 = SPH_T32(SSG2_1(W03) + W14 + SSG2_0(W06) + W05); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0x4ED8AA4A) + W05); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W06 = SPH_T32(SSG2_1(W04) + W15 + SSG2_0(W07) + W06); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0x5B9CCA4F) + W06); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W07 = SPH_T32(SSG2_1(W05) + W00 + SSG2_0(W08) + W07); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0x682E6FF3) + W07); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + W08 = SPH_T32(SSG2_1(W06) + W01 + SSG2_0(W09) + W08); \ + T1 = SPH_T32(H + BSG2_1(E) + CH(E, F, G) \ + + SPH_C32(0x748F82EE) + W08); \ + T2 = SPH_T32(BSG2_0(A) + MAJ(A, B, C)); \ + D = SPH_T32(D + T1); \ + H = SPH_T32(T1 + T2); \ + W09 = SPH_T32(SSG2_1(W07) + W02 + SSG2_0(W10) + W09); \ + T1 = SPH_T32(G + BSG2_1(D) + CH(D, E, F) \ + + SPH_C32(0x78A5636F) + W09); \ + T2 = SPH_T32(BSG2_0(H) + MAJ(H, A, B)); \ + C = SPH_T32(C + T1); \ + G = SPH_T32(T1 + T2); \ + W10 = SPH_T32(SSG2_1(W08) + W03 + SSG2_0(W11) + W10); \ + T1 = SPH_T32(F + BSG2_1(C) + CH(C, D, E) \ + + SPH_C32(0x84C87814) + W10); \ + T2 = SPH_T32(BSG2_0(G) + MAJ(G, H, A)); \ + B = SPH_T32(B + T1); \ + F = SPH_T32(T1 + T2); \ + W11 = SPH_T32(SSG2_1(W09) + W04 + SSG2_0(W12) + W11); \ + T1 = SPH_T32(E + BSG2_1(B) + CH(B, C, D) \ + + SPH_C32(0x8CC70208) + W11); \ + T2 = SPH_T32(BSG2_0(F) + MAJ(F, G, H)); \ + A = SPH_T32(A + T1); \ + E = SPH_T32(T1 + T2); \ + W12 = SPH_T32(SSG2_1(W10) + W05 + SSG2_0(W13) + W12); \ + T1 = SPH_T32(D + BSG2_1(A) + CH(A, B, C) \ + + SPH_C32(0x90BEFFFA) + W12); \ + T2 = SPH_T32(BSG2_0(E) + MAJ(E, F, G)); \ + H = SPH_T32(H + T1); \ + D = SPH_T32(T1 + T2); \ + W13 = SPH_T32(SSG2_1(W11) + W06 + SSG2_0(W14) + W13); \ + T1 = SPH_T32(C + BSG2_1(H) + CH(H, A, B) \ + + SPH_C32(0xA4506CEB) + W13); \ + T2 = SPH_T32(BSG2_0(D) + MAJ(D, E, F)); \ + G = SPH_T32(G + T1); \ + C = SPH_T32(T1 + T2); \ + W14 = SPH_T32(SSG2_1(W12) + W07 + SSG2_0(W15) + W14); \ + T1 = SPH_T32(B + BSG2_1(G) + CH(G, H, A) \ + + SPH_C32(0xBEF9A3F7) + W14); \ + T2 = SPH_T32(BSG2_0(C) + MAJ(C, D, E)); \ + F = SPH_T32(F + T1); \ + B = SPH_T32(T1 + T2); \ + W15 = SPH_T32(SSG2_1(W13) + W08 + SSG2_0(W00) + W15); \ + T1 = SPH_T32(A + BSG2_1(F) + CH(F, G, H) \ + + SPH_C32(0xC67178F2) + W15); \ + T2 = SPH_T32(BSG2_0(B) + MAJ(B, C, D)); \ + E = SPH_T32(E + T1); \ + A = SPH_T32(T1 + T2); \ + (r)[0] = SPH_T32((r)[0] + A); \ + (r)[1] = SPH_T32((r)[1] + B); \ + (r)[2] = SPH_T32((r)[2] + C); \ + (r)[3] = SPH_T32((r)[3] + D); \ + (r)[4] = SPH_T32((r)[4] + E); \ + (r)[5] = SPH_T32((r)[5] + F); \ + (r)[6] = SPH_T32((r)[6] + G); \ + (r)[7] = SPH_T32((r)[7] + H); \ + } while (0) + +#endif + +/* + * One round of SHA-224 / SHA-256. The data must be aligned for 32-bit access. + */ +static void +sha2_round(const unsigned char *data, sph_u32 r[8]) +{ +#define SHA2_IN(x) sph_dec32be_aligned(data + (4 * (x))) + SHA2_ROUND_BODY(SHA2_IN, r); +#undef SHA2_IN +} + +/* see sph_sha2.h */ +void +sph_sha224_init(void *cc) +{ + sph_sha224_context *sc; + + sc = cc; + memcpy(sc->val, H224, sizeof H224); +#if SPH_64 + sc->count = 0; +#else + sc->count_high = sc->count_low = 0; +#endif +} + +/* see sph_sha2.h */ +void +sph_sha256_init(void *cc) +{ + sph_sha256_context *sc; + + sc = cc; + memcpy(sc->val, H256, sizeof H256); +#if SPH_64 + sc->count = 0; +#else + sc->count_high = sc->count_low = 0; +#endif +} + +#define RFUN sha2_round +#define HASH sha224 +#define BE32 1 +#include "md_helper.c" + +/* see sph_sha2.h */ +void +sph_sha224_close(void *cc, void *dst) +{ + sha224_close(cc, dst, 7); + sph_sha224_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + sha224_addbits_and_close(cc, ub, n, dst, 7); + sph_sha224_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha256_close(void *cc, void *dst) +{ + sha224_close(cc, dst, 8); + sph_sha256_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + sha224_addbits_and_close(cc, ub, n, dst, 8); + sph_sha256_init(cc); +} + +/* see sph_sha2.h */ +void +sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8]) +{ +#define SHA2_IN(x) msg[x] + SHA2_ROUND_BODY(SHA2_IN, val); +#undef SHA2_IN +} diff --git a/stratum/algos/sph_sha2.h b/stratum/algos/sph_sha2.h new file mode 100644 index 000000000..c47b0f369 --- /dev/null +++ b/stratum/algos/sph_sha2.h @@ -0,0 +1,378 @@ +/* $Id: sph_sha2.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * SHA-224, SHA-256, SHA-384 and SHA-512 interface. + * + * SHA-256 has been published in FIPS 180-2, now amended with a change + * notice to include SHA-224 as well (which is a simple variation on + * SHA-256). SHA-384 and SHA-512 are also defined in FIPS 180-2. FIPS + * standards can be found at: + * http://csrc.nist.gov/publications/fips/ + * + * ==========================(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_sha2.h + * @author Thomas Pornin + */ + +#ifndef SPH_SHA2_H__ +#define SPH_SHA2_H__ + +#include +#include "sph_types.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * Output size (in bits) for SHA-224. + */ +#define SPH_SIZE_sha224 224 + +/** + * Output size (in bits) for SHA-256. + */ +#define SPH_SIZE_sha256 256 + +/** + * This structure is a context for SHA-224 computations: it contains the + * intermediate values and some data from the last entered block. Once + * a SHA-224 computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running SHA-224 computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + sph_u32 val[8]; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_sha224_context; + +/** + * This structure is a context for SHA-256 computations. It is identical + * to the SHA-224 context. However, a context is initialized for SHA-224 + * or SHA-256, but not both (the internal IV is not the + * same). + */ +typedef sph_sha224_context sph_sha256_context; + +/** + * Initialize a SHA-224 context. This process performs no memory allocation. + * + * @param cc the SHA-224 context (pointer to + * a sph_sha224_context) + */ +void sph_sha224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHA-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha224(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHA-224 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-224 context + * @param dst the destination buffer + */ +void sph_sha224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha224_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Apply the SHA-224 compression function on the provided data. The + * msg parameter contains the 16 32-bit input blocks, + * as numerical values (hence after the big-endian decoding). The + * val parameter contains the 8 32-bit input blocks for + * the compression function; the output is written in place in this + * array. + * + * @param msg the message block (16 values) + * @param val the function 256-bit input and output + */ +void sph_sha224_comp(const sph_u32 msg[16], sph_u32 val[8]); + +/** + * Initialize a SHA-256 context. This process performs no memory allocation. + * + * @param cc the SHA-256 context (pointer to + * a sph_sha256_context) + */ +void sph_sha256_init(void *cc); + +#ifdef DOXYGEN_IGNORE +/** + * Process some data bytes, for SHA-256. This function is identical to + * sha_224() + * + * @param cc the SHA-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha256(void *cc, const void *data, size_t len); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha256 sph_sha224 +#endif + +/** + * Terminate the current SHA-256 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-256 context + * @param dst the destination buffer + */ +void sph_sha256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef DOXYGEN_IGNORE +/** + * Apply the SHA-256 compression function on the provided data. This + * function is identical to sha224_comp(). + * + * @param msg the message block (16 values) + * @param val the function 256-bit input and output + */ +void sph_sha256_comp(const sph_u32 msg[16], sph_u32 val[8]); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha256_comp sph_sha224_comp +#endif + +#if SPH_64 + +/** + * Output size (in bits) for SHA-384. + */ +#define SPH_SIZE_sha384 384 + +/** + * Output size (in bits) for SHA-512. + */ +#define SPH_SIZE_sha512 512 + +/** + * This structure is a context for SHA-384 computations: it contains the + * intermediate values and some data from the last entered block. Once + * a SHA-384 computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running SHA-384 computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + sph_u64 val[8]; + sph_u64 count; +#endif +} sph_sha384_context; + +/** + * Initialize a SHA-384 context. This process performs no memory allocation. + * + * @param cc the SHA-384 context (pointer to + * a sph_sha384_context) + */ +void sph_sha384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHA-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha384(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHA-384 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-384 context + * @param dst the destination buffer + */ +void sph_sha384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha384_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Apply the SHA-384 compression function on the provided data. The + * msg parameter contains the 16 64-bit input blocks, + * as numerical values (hence after the big-endian decoding). The + * val parameter contains the 8 64-bit input blocks for + * the compression function; the output is written in place in this + * array. + * + * @param msg the message block (16 values) + * @param val the function 512-bit input and output + */ +void sph_sha384_comp(const sph_u64 msg[16], sph_u64 val[8]); + +/** + * This structure is a context for SHA-512 computations. It is identical + * to the SHA-384 context. However, a context is initialized for SHA-384 + * or SHA-512, but not both (the internal IV is not the + * same). + */ +typedef sph_sha384_context sph_sha512_context; + +/** + * Initialize a SHA-512 context. This process performs no memory allocation. + * + * @param cc the SHA-512 context (pointer to + * a sph_sha512_context) + */ +void sph_sha512_init(void *cc); + +#ifdef DOXYGEN_IGNORE +/** + * Process some data bytes, for SHA-512. This function is identical to + * sph_sha384(). + * + * @param cc the SHA-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_sha512(void *cc, const void *data, size_t len); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha512 sph_sha384 +#endif + +/** + * Terminate the current SHA-512 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHA-512 context + * @param dst the destination buffer + */ +void sph_sha512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHA-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_sha512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef DOXYGEN_IGNORE +/** + * Apply the SHA-512 compression function. This function is identical to + * sph_sha384_comp(). + * + * @param msg the message block (16 values) + * @param val the function 512-bit input and output + */ +void sph_sha512_comp(const sph_u64 msg[16], sph_u64 val[8]); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_sha512_comp sph_sha384_comp +#endif + +#endif + +#endif +#ifdef __cplusplus +} +#endif + diff --git a/stratum/algos/sph_shabal.h b/stratum/algos/sph_shabal.h new file mode 100644 index 000000000..9ee6c81dd --- /dev/null +++ b/stratum/algos/sph_shabal.h @@ -0,0 +1,344 @@ +/* $Id: sph_shabal.h 175 2010-05-07 16:03:20Z tp $ */ +/** + * Shabal interface. Shabal is a family of functions which differ by + * their output size; this implementation defines Shabal for output + * sizes 192, 224, 256, 384 and 512 bits. + * + * ==========================(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_shabal.h + * @author Thomas Pornin + */ + +#ifndef SPH_SHABAL_H__ +#define SPH_SHABAL_H__ + +#include +#include "sph_types.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * Output size (in bits) for Shabal-192. + */ +#define SPH_SIZE_shabal192 192 + +/** + * Output size (in bits) for Shabal-224. + */ +#define SPH_SIZE_shabal224 224 + +/** + * Output size (in bits) for Shabal-256. + */ +#define SPH_SIZE_shabal256 256 + +/** + * Output size (in bits) for Shabal-384. + */ +#define SPH_SIZE_shabal384 384 + +/** + * Output size (in bits) for Shabal-512. + */ +#define SPH_SIZE_shabal512 512 + +/** + * This structure is a context for Shabal computations: it contains the + * intermediate values and some data from the last entered block. Once + * a Shabal computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running Shabal computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 A[12], B[16], C[16]; + sph_u32 Whigh, Wlow; +#endif +} sph_shabal_context; + +/** + * Type for a Shabal-192 context (identical to the common context). + */ +typedef sph_shabal_context sph_shabal192_context; + +/** + * Type for a Shabal-224 context (identical to the common context). + */ +typedef sph_shabal_context sph_shabal224_context; + +/** + * Type for a Shabal-256 context (identical to the common context). + */ +typedef sph_shabal_context sph_shabal256_context; + +/** + * Type for a Shabal-384 context (identical to the common context). + */ +typedef sph_shabal_context sph_shabal384_context; + +/** + * Type for a Shabal-512 context (identical to the common context). + */ +typedef sph_shabal_context sph_shabal512_context; + +/** + * Initialize a Shabal-192 context. This process performs no memory allocation. + * + * @param cc the Shabal-192 context (pointer to a + * sph_shabal192_context) + */ +void sph_shabal192_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Shabal-192 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shabal192(void *cc, const void *data, size_t len); + +/** + * Terminate the current Shabal-192 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (24 bytes). The context is automatically + * reinitialized. + * + * @param cc the Shabal-192 context + * @param dst the destination buffer + */ +void sph_shabal192_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (24 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Shabal-192 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shabal192_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Shabal-224 context. This process performs no memory allocation. + * + * @param cc the Shabal-224 context (pointer to a + * sph_shabal224_context) + */ +void sph_shabal224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Shabal-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shabal224(void *cc, const void *data, size_t len); + +/** + * Terminate the current Shabal-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the Shabal-224 context + * @param dst the destination buffer + */ +void sph_shabal224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Shabal-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shabal224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Shabal-256 context. This process performs no memory allocation. + * + * @param cc the Shabal-256 context (pointer to a + * sph_shabal256_context) + */ +void sph_shabal256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Shabal-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shabal256(void *cc, const void *data, size_t len); + +/** + * Terminate the current Shabal-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the Shabal-256 context + * @param dst the destination buffer + */ +void sph_shabal256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Shabal-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shabal256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Shabal-384 context. This process performs no memory allocation. + * + * @param cc the Shabal-384 context (pointer to a + * sph_shabal384_context) + */ +void sph_shabal384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Shabal-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shabal384(void *cc, const void *data, size_t len); + +/** + * Terminate the current Shabal-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the Shabal-384 context + * @param dst the destination buffer + */ +void sph_shabal384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Shabal-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shabal384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Shabal-512 context. This process performs no memory allocation. + * + * @param cc the Shabal-512 context (pointer to a + * sph_shabal512_context) + */ +void sph_shabal512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Shabal-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shabal512(void *cc, const void *data, size_t len); + +/** + * Terminate the current Shabal-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the Shabal-512 context + * @param dst the destination buffer + */ +void sph_shabal512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Shabal-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shabal512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_shavite.h b/stratum/algos/sph_shavite.h new file mode 100644 index 000000000..0957e42a9 --- /dev/null +++ b/stratum/algos/sph_shavite.h @@ -0,0 +1,314 @@ +/* $Id: sph_shavite.h 208 2010-06-02 20:33:00Z tp $ */ +/** + * SHAvite-3 interface. This code implements SHAvite-3 with the + * recommended parameters for SHA-3, with outputs of 224, 256, 384 and + * 512 bits. In the following, we call the function "SHAvite" (without + * the "-3" suffix), thus "SHAvite-224" is "SHAvite-3 with a 224-bit + * output". + * + * ==========================(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_shavite.h + * @author Thomas Pornin + */ + +#ifndef SPH_SHAVITE_H__ +#define SPH_SHAVITE_H__ + +#include +#include "sph_types.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +/** + * Output size (in bits) for SHAvite-224. + */ +#define SPH_SIZE_shavite224 224 + +/** + * Output size (in bits) for SHAvite-256. + */ +#define SPH_SIZE_shavite256 256 + +/** + * Output size (in bits) for SHAvite-384. + */ +#define SPH_SIZE_shavite384 384 + +/** + * Output size (in bits) for SHAvite-512. + */ +#define SPH_SIZE_shavite512 512 + +/** + * This structure is a context for SHAvite-224 and SHAvite-256 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a SHAvite computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running SHAvite + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 h[8]; + sph_u32 count0, count1; +#endif +} sph_shavite_small_context; + +/** + * This structure is a context for SHAvite-224 computations. It is + * identical to the common sph_shavite_small_context. + */ +typedef sph_shavite_small_context sph_shavite224_context; + +/** + * This structure is a context for SHAvite-256 computations. It is + * identical to the common sph_shavite_small_context. + */ +typedef sph_shavite_small_context sph_shavite256_context; + +/** + * This structure is a context for SHAvite-384 and SHAvite-512 computations: + * it contains the intermediate values and some data from the last + * entered block. Once a SHAvite computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running SHAvite + * computation can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u32 h[16]; + sph_u32 count0, count1, count2, count3; +#endif +} sph_shavite_big_context; + +/** + * This structure is a context for SHAvite-384 computations. It is + * identical to the common sph_shavite_small_context. + */ +typedef sph_shavite_big_context sph_shavite384_context; + +/** + * This structure is a context for SHAvite-512 computations. It is + * identical to the common sph_shavite_small_context. + */ +typedef sph_shavite_big_context sph_shavite512_context; + +/** + * Initialize a SHAvite-224 context. This process performs no memory allocation. + * + * @param cc the SHAvite-224 context (pointer to a + * sph_shavite224_context) + */ +void sph_shavite224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHAvite-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shavite224(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHAvite-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHAvite-224 context + * @param dst the destination buffer + */ +void sph_shavite224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHAvite-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shavite224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a SHAvite-256 context. This process performs no memory allocation. + * + * @param cc the SHAvite-256 context (pointer to a + * sph_shavite256_context) + */ +void sph_shavite256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHAvite-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shavite256(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHAvite-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHAvite-256 context + * @param dst the destination buffer + */ +void sph_shavite256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHAvite-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shavite256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a SHAvite-384 context. This process performs no memory allocation. + * + * @param cc the SHAvite-384 context (pointer to a + * sph_shavite384_context) + */ +void sph_shavite384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHAvite-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shavite384(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHAvite-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHAvite-384 context + * @param dst the destination buffer + */ +void sph_shavite384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHAvite-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shavite384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a SHAvite-512 context. This process performs no memory allocation. + * + * @param cc the SHAvite-512 context (pointer to a + * sph_shavite512_context) + */ +void sph_shavite512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SHAvite-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_shavite512(void *cc, const void *data, size_t len); + +/** + * Terminate the current SHAvite-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the SHAvite-512 context + * @param dst the destination buffer + */ +void sph_shavite512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SHAvite-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_shavite512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_simd.h b/stratum/algos/sph_simd.h new file mode 100644 index 000000000..92ee1e727 --- /dev/null +++ b/stratum/algos/sph_simd.h @@ -0,0 +1,309 @@ +/* $Id: sph_simd.h 154 2010-04-26 17:00:24Z tp $ */ +/** + * SIMD interface. SIMD is a family of functions which differ by + * their output size; this implementation defines SIMD for output + * sizes 224, 256, 384 and 512 bits. + * + * ==========================(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_simd.h + * @author Thomas Pornin + */ + +#ifndef SPH_SIMD_H__ +#define SPH_SIMD_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for SIMD-224. + */ +#define SPH_SIZE_simd224 224 + +/** + * Output size (in bits) for SIMD-256. + */ +#define SPH_SIZE_simd256 256 + +/** + * Output size (in bits) for SIMD-384. + */ +#define SPH_SIZE_simd384 384 + +/** + * Output size (in bits) for SIMD-512. + */ +#define SPH_SIZE_simd512 512 + +/** + * This structure is a context for SIMD computations: it contains the + * intermediate values and some data from the last entered block. Once + * an SIMD computation has been performed, the context can be reused for + * another computation. This specific structure is used for SIMD-224 + * and SIMD-256. + * + * The contents of this structure are private. A running SIMD computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 state[16]; + sph_u32 count_low, count_high; +#endif +} sph_simd_small_context; + +/** + * This structure is a context for SIMD computations: it contains the + * intermediate values and some data from the last entered block. Once + * an SIMD computation has been performed, the context can be reused for + * another computation. This specific structure is used for SIMD-384 + * and SIMD-512. + * + * The contents of this structure are private. A running SIMD computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + size_t ptr; + sph_u32 state[32]; + sph_u32 count_low, count_high; +#endif +} sph_simd_big_context; + +/** + * Type for a SIMD-224 context (identical to the common "small" context). + */ +typedef sph_simd_small_context sph_simd224_context; + +/** + * Type for a SIMD-256 context (identical to the common "small" context). + */ +typedef sph_simd_small_context sph_simd256_context; + +/** + * Type for a SIMD-384 context (identical to the common "big" context). + */ +typedef sph_simd_big_context sph_simd384_context; + +/** + * Type for a SIMD-512 context (identical to the common "big" context). + */ +typedef sph_simd_big_context sph_simd512_context; + +/** + * Initialize an SIMD-224 context. This process performs no memory allocation. + * + * @param cc the SIMD-224 context (pointer to a + * sph_simd224_context) + */ +void sph_simd224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SIMD-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_simd224(void *cc, const void *data, size_t len); + +/** + * Terminate the current SIMD-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the SIMD-224 context + * @param dst the destination buffer + */ +void sph_simd224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SIMD-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_simd224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize an SIMD-256 context. This process performs no memory allocation. + * + * @param cc the SIMD-256 context (pointer to a + * sph_simd256_context) + */ +void sph_simd256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SIMD-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_simd256(void *cc, const void *data, size_t len); + +/** + * Terminate the current SIMD-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the SIMD-256 context + * @param dst the destination buffer + */ +void sph_simd256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SIMD-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_simd256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize an SIMD-384 context. This process performs no memory allocation. + * + * @param cc the SIMD-384 context (pointer to a + * sph_simd384_context) + */ +void sph_simd384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SIMD-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_simd384(void *cc, const void *data, size_t len); + +/** + * Terminate the current SIMD-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the SIMD-384 context + * @param dst the destination buffer + */ +void sph_simd384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SIMD-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_simd384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize an SIMD-512 context. This process performs no memory allocation. + * + * @param cc the SIMD-512 context (pointer to a + * sph_simd512_context) + */ +void sph_simd512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the SIMD-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_simd512(void *cc, const void *data, size_t len); + +/** + * Terminate the current SIMD-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the SIMD-512 context + * @param dst the destination buffer + */ +void sph_simd512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the SIMD-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_simd512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_skein.h b/stratum/algos/sph_skein.h new file mode 100644 index 000000000..bddbc86fa --- /dev/null +++ b/stratum/algos/sph_skein.h @@ -0,0 +1,298 @@ +/* $Id: sph_skein.h 253 2011-06-07 18:33:10Z tp $ */ +/** + * Skein interface. The Skein specification defines three main + * functions, called Skein-256, Skein-512 and Skein-1024, which can be + * further parameterized with an output length. For the SHA-3 + * competition, Skein-512 is used for output sizes of 224, 256, 384 and + * 512 bits; this is what this code implements. Thus, we hereafter call + * Skein-224, Skein-256, Skein-384 and Skein-512 what the Skein + * specification defines as Skein-512-224, Skein-512-256, Skein-512-384 + * and Skein-512-512, respectively. + * + * ==========================(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_skein.h + * @author Thomas Pornin + */ + +#ifndef SPH_SKEIN_H__ +#define SPH_SKEIN_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +#if SPH_64 + +/** + * Output size (in bits) for Skein-224. + */ +#define SPH_SIZE_skein224 224 + +/** + * Output size (in bits) for Skein-256. + */ +#define SPH_SIZE_skein256 256 + +/** + * Output size (in bits) for Skein-384. + */ +#define SPH_SIZE_skein384 384 + +/** + * Output size (in bits) for Skein-512. + */ +#define SPH_SIZE_skein512 512 + +/** + * This structure is a context for Skein computations (with a 384- or + * 512-bit output): it contains the intermediate values and some data + * from the last entered block. Once a Skein computation has been + * performed, the context can be reused for another computation. + * + * The contents of this structure are private. A running Skein computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u64 h0, h1, h2, h3, h4, h5, h6, h7; + sph_u64 bcount; +#endif +} sph_skein_big_context; + +/** + * Type for a Skein-224 context (identical to the common "big" context). + */ +typedef sph_skein_big_context sph_skein224_context; + +/** + * Type for a Skein-256 context (identical to the common "big" context). + */ +typedef sph_skein_big_context sph_skein256_context; + +/** + * Type for a Skein-384 context (identical to the common "big" context). + */ +typedef sph_skein_big_context sph_skein384_context; + +/** + * Type for a Skein-512 context (identical to the common "big" context). + */ +typedef sph_skein_big_context sph_skein512_context; + +/** + * Initialize a Skein-224 context. This process performs no memory allocation. + * + * @param cc the Skein-224 context (pointer to a + * sph_skein224_context) + */ +void sph_skein224_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Skein-224 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_skein224(void *cc, const void *data, size_t len); + +/** + * Terminate the current Skein-224 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the Skein-224 context + * @param dst the destination buffer + */ +void sph_skein224_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (28 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Skein-224 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_skein224_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Skein-256 context. This process performs no memory allocation. + * + * @param cc the Skein-256 context (pointer to a + * sph_skein256_context) + */ +void sph_skein256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Skein-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_skein256(void *cc, const void *data, size_t len); + +/** + * Terminate the current Skein-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the Skein-256 context + * @param dst the destination buffer + */ +void sph_skein256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Skein-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_skein256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Skein-384 context. This process performs no memory allocation. + * + * @param cc the Skein-384 context (pointer to a + * sph_skein384_context) + */ +void sph_skein384_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Skein-384 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_skein384(void *cc, const void *data, size_t len); + +/** + * Terminate the current Skein-384 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (48 bytes). The context is automatically + * reinitialized. + * + * @param cc the Skein-384 context + * @param dst the destination buffer + */ +void sph_skein384_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (48 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Skein-384 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_skein384_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Skein-512 context. This process performs no memory allocation. + * + * @param cc the Skein-512 context (pointer to a + * sph_skein512_context) + */ +void sph_skein512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Skein-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_skein512(void *cc, const void *data, size_t len); + +/** + * Terminate the current Skein-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the Skein-512 context + * @param dst the destination buffer + */ +void sph_skein512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the Skein-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_skein512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/algos/sph_types.h b/stratum/algos/sph_types.h new file mode 100644 index 000000000..7295b0b37 --- /dev/null +++ b/stratum/algos/sph_types.h @@ -0,0 +1,1976 @@ +/* $Id: sph_types.h 260 2011-07-21 01:02:38Z tp $ */ +/** + * 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 unsigned char 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 + */ + +#ifndef SPH_TYPES_H__ +#define SPH_TYPES_H__ + +#include + +/* + * 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 + +/* ============= BEGIN documentation block for Doxygen ============ */ + +#ifdef DOXYGEN_IGNORE + +/** @mainpage sphlib C code documentation + * + * @section overview Overview + * + * sphlib is a library which contains implementations of + * various cryptographic hash functions. These pages have been generated + * with doxygen and + * document the API for the C implementations. + * + * The API is described in appropriate header files, which are available + * in the "Files" section. Each hash function family has its own header, + * whose name begins with "sph_" and contains the family + * name. For instance, the API for the RIPEMD hash functions is available + * in the header file sph_ripemd.h. + * + * @section principles API structure and conventions + * + * @subsection io Input/output conventions + * + * In all generality, hash functions operate over strings of bits. + * Individual bits are rarely encountered in C programming or actual + * communication protocols; most protocols converge on the ubiquitous + * "octet" which is a group of eight bits. Data is thus expressed as a + * stream of octets. The C programming language contains the notion of a + * "byte", which is a data unit managed under the type "unsigned + * char". The C standard prescribes that a byte should hold at + * least eight bits, but possibly more. Most modern architectures, even + * in the embedded world, feature eight-bit bytes, i.e. map bytes to + * octets. + * + * Nevertheless, for some of the implemented hash functions, an extra + * API has been added, which allows the input of arbitrary sequences of + * bits: when the computation is about to be closed, 1 to 7 extra bits + * can be added. The functions for which this API is implemented include + * the SHA-2 functions and all SHA-3 candidates. + * + * sphlib defines hash function which may hash octet streams, + * i.e. streams of bits where the number of bits is a multiple of eight. + * The data input functions in the sphlib API expect data + * as anonymous pointers ("const void *") with a length + * (of type "size_t") which gives the input data chunk length + * in bytes. A byte is assumed to be an octet; the sph_types.h + * header contains a compile-time test which prevents compilation on + * architectures where this property is not met. + * + * The hash function output is also converted into bytes. All currently + * implemented hash functions have an output width which is a multiple of + * eight, and this is likely to remain true for new designs. + * + * Most hash functions internally convert input data into 32-bit of 64-bit + * words, using either little-endian or big-endian conversion. The hash + * output also often consists of such words, which are encoded into output + * bytes with a similar endianness convention. Some hash functions have + * been only loosely specified on that subject; when necessary, + * sphlib has been tested against published "reference" + * implementations in order to use the same conventions. + * + * @subsection shortname Function short name + * + * Each implemented hash function has a "short name" which is used + * internally to derive the identifiers for the functions and context + * structures which the function uses. For instance, MD5 has the short + * name "md5". Short names are listed in the next section, + * for the implemented hash functions. In subsequent sections, the + * short name will be assumed to be "XXX": replace with the + * actual hash function name to get the C identifier. + * + * Note: some functions within the same family share the same core + * elements, such as update function or context structure. Correspondingly, + * some of the defined types or functions may actually be macros which + * transparently evaluate to another type or function name. + * + * @subsection context Context structure + * + * Each implemented hash fonction has its own context structure, available + * under the type name "sph_XXX_context" for the hash function + * with short name "XXX". This structure holds all needed + * state for a running hash computation. + * + * The contents of these structures are meant to be opaque, and private + * to the implementation. However, these contents are specified in the + * header files so that application code which uses sphlib + * may access the size of those structures. + * + * The caller is responsible for allocating the context structure, + * whether by dynamic allocation (malloc() or equivalent), + * static allocation (a global permanent variable), as an automatic + * variable ("on the stack"), or by any other mean which ensures proper + * structure alignment. sphlib code performs no dynamic + * allocation by itself. + * + * The context must be initialized before use, using the + * sph_XXX_init() function. This function sets the context + * state to proper initial values for hashing. + * + * Since all state data is contained within the context structure, + * sphlib is thread-safe and reentrant: several hash + * computations may be performed in parallel, provided that they do not + * operate on the same context. Moreover, a running computation can be + * cloned by copying the context (with a simple memcpy()): + * the context and its clone are then independant and may be updated + * with new data and/or closed without interfering with each other. + * Similarly, a context structure can be moved in memory at will: + * context structures contain no pointer, in particular no pointer to + * themselves. + * + * @subsection dataio Data input + * + * Hashed data is input with the sph_XXX() fonction, which + * takes as parameters a pointer to the context, a pointer to the data + * to hash, and the number of data bytes to hash. The context is updated + * with the new data. + * + * Data can be input in one or several calls, with arbitrary input lengths. + * However, it is best, performance wise, to input data by relatively big + * chunks (say a few kilobytes), because this allows sphlib to + * optimize things and avoid internal copying. + * + * When all data has been input, the context can be closed with + * sph_XXX_close(). The hash output is computed and written + * into the provided buffer. The caller must take care to provide a + * buffer of appropriate length; e.g., when using SHA-1, the output is + * a 20-byte word, therefore the output buffer must be at least 20-byte + * long. + * + * For some hash functions, the sph_XXX_addbits_and_close() + * function can be used instead of sph_XXX_close(). This + * function can take a few extra bits to be added at + * the end of the input message. This allows hashing messages with a + * bit length which is not a multiple of 8. The extra bits are provided + * as an unsigned integer value, and a bit count. The bit count must be + * between 0 and 7, inclusive. The extra bits are provided as bits 7 to + * 0 (bits of numerical value 128, 64, 32... downto 0), in that order. + * For instance, to add three bits of value 1, 1 and 0, the unsigned + * integer will have value 192 (1*128 + 1*64 + 0*32) and the bit count + * will be 3. + * + * The SPH_SIZE_XXX macro is defined for each hash function; + * it evaluates to the function output size, expressed in bits. For instance, + * SPH_SIZE_sha1 evaluates to 160. + * + * When closed, the context is automatically reinitialized and can be + * immediately used for another computation. It is not necessary to call + * sph_XXX_init() after a close. Note that + * sph_XXX_init() can still be called to "reset" a context, + * i.e. forget previously input data, and get back to the initial state. + * + * @subsection alignment Data alignment + * + * "Alignment" is a property of data, which is said to be "properly + * aligned" when its emplacement in memory is such that the data can + * be optimally read by full words. This depends on the type of access; + * basically, some hash functions will read data by 32-bit or 64-bit + * words. sphlib does not mandate such alignment for input + * data, but using aligned data can substantially improve performance. + * + * As a rule, it is best to input data by chunks whose length (in bytes) + * is a multiple of eight, and which begins at "generally aligned" + * addresses, such as the base address returned by a call to + * malloc(). + * + * @section functions Implemented functions + * + * We give here the list of implemented functions. They are grouped by + * family; to each family corresponds a specific header file. Each + * individual function has its associated "short name". Please refer to + * the documentation for that header file to get details on the hash + * function denomination and provenance. + * + * Note: the functions marked with a '(64)' in the list below are + * available only if the C compiler provides an integer type of length + * 64 bits or more. Such a type is mandatory in the latest C standard + * (ISO 9899:1999, aka "C99") and is present in several older compilers + * as well, so chances are that such a type is available. + * + * - HAVAL family: file sph_haval.h + * - HAVAL-128/3 (128-bit, 3 passes): short name: haval128_3 + * - HAVAL-128/4 (128-bit, 4 passes): short name: haval128_4 + * - HAVAL-128/5 (128-bit, 5 passes): short name: haval128_5 + * - HAVAL-160/3 (160-bit, 3 passes): short name: haval160_3 + * - HAVAL-160/4 (160-bit, 4 passes): short name: haval160_4 + * - HAVAL-160/5 (160-bit, 5 passes): short name: haval160_5 + * - HAVAL-192/3 (192-bit, 3 passes): short name: haval192_3 + * - HAVAL-192/4 (192-bit, 4 passes): short name: haval192_4 + * - HAVAL-192/5 (192-bit, 5 passes): short name: haval192_5 + * - HAVAL-224/3 (224-bit, 3 passes): short name: haval224_3 + * - HAVAL-224/4 (224-bit, 4 passes): short name: haval224_4 + * - HAVAL-224/5 (224-bit, 5 passes): short name: haval224_5 + * - HAVAL-256/3 (256-bit, 3 passes): short name: haval256_3 + * - HAVAL-256/4 (256-bit, 4 passes): short name: haval256_4 + * - HAVAL-256/5 (256-bit, 5 passes): short name: haval256_5 + * - MD2: file sph_md2.h, short name: md2 + * - MD4: file sph_md4.h, short name: md4 + * - MD5: file sph_md5.h, short name: md5 + * - PANAMA: file sph_panama.h, short name: panama + * - RadioGatun family: file sph_radiogatun.h + * - RadioGatun[32]: short name: radiogatun32 + * - RadioGatun[64]: short name: radiogatun64 (64) + * - RIPEMD family: file sph_ripemd.h + * - RIPEMD: short name: ripemd + * - RIPEMD-128: short name: ripemd128 + * - RIPEMD-160: short name: ripemd160 + * - SHA-0: file sph_sha0.h, short name: sha0 + * - SHA-1: file sph_sha1.h, short name: sha1 + * - SHA-2 family, 32-bit hashes: file sph_sha2.h + * - SHA-224: short name: sha224 + * - SHA-256: short name: sha256 + * - SHA-384: short name: sha384 (64) + * - SHA-512: short name: sha512 (64) + * - Tiger family: file sph_tiger.h + * - Tiger: short name: tiger (64) + * - Tiger2: short name: tiger2 (64) + * - WHIRLPOOL family: file sph_whirlpool.h + * - WHIRLPOOL-0: short name: whirlpool0 (64) + * - WHIRLPOOL-1: short name: whirlpool1 (64) + * - WHIRLPOOL: short name: whirlpool (64) + * + * The fourteen second-round SHA-3 candidates are also implemented; + * when applicable, the implementations follow the "final" specifications + * as published for the third round of the SHA-3 competition (BLAKE, + * Groestl, JH, Keccak and Skein have been tweaked for third round). + * + * - BLAKE family: file sph_blake.h + * - BLAKE-224: short name: blake224 + * - BLAKE-256: short name: blake256 + * - BLAKE-384: short name: blake384 + * - BLAKE-512: short name: blake512 + * - BMW (Blue Midnight Wish) family: file sph_bmw.h + * - BMW-224: short name: bmw224 + * - BMW-256: short name: bmw256 + * - BMW-384: short name: bmw384 (64) + * - BMW-512: short name: bmw512 (64) + * - CubeHash family: file sph_cubehash.h (specified as + * CubeHash16/32 in the CubeHash specification) + * - CubeHash-224: short name: cubehash224 + * - CubeHash-256: short name: cubehash256 + * - CubeHash-384: short name: cubehash384 + * - CubeHash-512: short name: cubehash512 + * - ECHO family: file sph_echo.h + * - ECHO-224: short name: echo224 + * - ECHO-256: short name: echo256 + * - ECHO-384: short name: echo384 + * - ECHO-512: short name: echo512 + * - Fugue family: file sph_fugue.h + * - Fugue-224: short name: fugue224 + * - Fugue-256: short name: fugue256 + * - Fugue-384: short name: fugue384 + * - Fugue-512: short name: fugue512 + * - Groestl family: file sph_groestl.h + * - Groestl-224: short name: groestl224 + * - Groestl-256: short name: groestl256 + * - Groestl-384: short name: groestl384 + * - Groestl-512: short name: groestl512 + * - Hamsi family: file sph_hamsi.h + * - Hamsi-224: short name: hamsi224 + * - Hamsi-256: short name: hamsi256 + * - Hamsi-384: short name: hamsi384 + * - Hamsi-512: short name: hamsi512 + * - JH family: file sph_jh.h + * - JH-224: short name: jh224 + * - JH-256: short name: jh256 + * - JH-384: short name: jh384 + * - JH-512: short name: jh512 + * - Keccak family: file sph_keccak.h + * - Keccak-224: short name: keccak224 + * - Keccak-256: short name: keccak256 + * - Keccak-384: short name: keccak384 + * - Keccak-512: short name: keccak512 + * - Luffa family: file sph_luffa.h + * - Luffa-224: short name: luffa224 + * - Luffa-256: short name: luffa256 + * - Luffa-384: short name: luffa384 + * - Luffa-512: short name: luffa512 + * - Shabal family: file sph_shabal.h + * - Shabal-192: short name: shabal192 + * - Shabal-224: short name: shabal224 + * - Shabal-256: short name: shabal256 + * - Shabal-384: short name: shabal384 + * - Shabal-512: short name: shabal512 + * - SHAvite-3 family: file sph_shavite.h + * - SHAvite-224 (nominally "SHAvite-3 with 224-bit output"): + * short name: shabal224 + * - SHAvite-256 (nominally "SHAvite-3 with 256-bit output"): + * short name: shabal256 + * - SHAvite-384 (nominally "SHAvite-3 with 384-bit output"): + * short name: shabal384 + * - SHAvite-512 (nominally "SHAvite-3 with 512-bit output"): + * short name: shabal512 + * - SIMD family: file sph_simd.h + * - SIMD-224: short name: simd224 + * - SIMD-256: short name: simd256 + * - SIMD-384: short name: simd384 + * - SIMD-512: short name: simd512 + * - Skein family: file sph_skein.h + * - Skein-224 (nominally specified as Skein-512-224): short name: + * skein224 (64) + * - Skein-256 (nominally specified as Skein-512-256): short name: + * skein256 (64) + * - Skein-384 (nominally specified as Skein-512-384): short name: + * skein384 (64) + * - Skein-512 (nominally specified as Skein-512-512): short name: + * skein512 (64) + * + * For the second-round SHA-3 candidates, the functions are as specified + * for round 2, i.e. with the "tweaks" that some candidates added + * between round 1 and round 2. Also, some of the submitted packages for + * round 2 contained errors, in the specification, reference code, or + * both. sphlib implements the corrected versions. + */ + +/** @hideinitializer + * Unsigned integer type whose length is at least 32 bits; on most + * architectures, it will have a width of exactly 32 bits. Unsigned C + * types implement arithmetics modulo a power of 2; use the + * SPH_T32() macro to ensure that the value is truncated + * to exactly 32 bits. Unless otherwise specified, all macros and + * functions which accept sph_u32 values assume that these + * values fit on 32 bits, i.e. do not exceed 2^32-1, even on architectures + * where sph_u32 is larger than that. + */ +typedef __arch_dependant__ sph_u32; + +/** @hideinitializer + * Signed integer type corresponding to sph_u32; it has + * width 32 bits or more. + */ +typedef __arch_dependant__ sph_s32; + +/** @hideinitializer + * Unsigned integer type whose length is at least 64 bits; on most + * architectures which feature such a type, it will have a width of + * exactly 64 bits. C99-compliant platform will have this type; it + * is also defined when the GNU compiler (gcc) is used, and on + * platforms where unsigned long is large enough. If this + * type is not available, then some hash functions which depends on + * a 64-bit type will not be available (most notably SHA-384, SHA-512, + * Tiger and WHIRLPOOL). + */ +typedef __arch_dependant__ sph_u64; + +/** @hideinitializer + * Signed integer type corresponding to sph_u64; it has + * width 64 bits or more. + */ +typedef __arch_dependant__ sph_s64; + +/** + * This macro expands the token x into a suitable + * constant expression of type sph_u32. Depending on + * how this type is defined, a suffix such as UL may + * be appended to the argument. + * + * @param x the token to expand into a suitable constant expression + */ +#define SPH_C32(x) + +/** + * Truncate a 32-bit value to exactly 32 bits. On most systems, this is + * a no-op, recognized as such by the compiler. + * + * @param x the value to truncate (of type sph_u32) + */ +#define SPH_T32(x) + +/** + * Rotate a 32-bit value by a number of bits to the left. The rotate + * count must reside between 1 and 31. This macro assumes that its + * first argument fits in 32 bits (no extra bit allowed on machines where + * sph_u32 is wider); both arguments may be evaluated + * several times. + * + * @param x the value to rotate (of type sph_u32) + * @param n the rotation count (between 1 and 31, inclusive) + */ +#define SPH_ROTL32(x, n) + +/** + * Rotate a 32-bit value by a number of bits to the left. The rotate + * count must reside between 1 and 31. This macro assumes that its + * first argument fits in 32 bits (no extra bit allowed on machines where + * sph_u32 is wider); both arguments may be evaluated + * several times. + * + * @param x the value to rotate (of type sph_u32) + * @param n the rotation count (between 1 and 31, inclusive) + */ +#define SPH_ROTR32(x, n) + +/** + * This macro is defined on systems for which a 64-bit type has been + * detected, and is used for sph_u64. + */ +#define SPH_64 + +/** + * This macro is defined on systems for the "native" integer size is + * 64 bits (64-bit values fit in one register). + */ +#define SPH_64_TRUE + +/** + * This macro expands the token x into a suitable + * constant expression of type sph_u64. Depending on + * how this type is defined, a suffix such as ULL may + * be appended to the argument. This macro is defined only if a + * 64-bit type was detected and used for sph_u64. + * + * @param x the token to expand into a suitable constant expression + */ +#define SPH_C64(x) + +/** + * Truncate a 64-bit value to exactly 64 bits. On most systems, this is + * a no-op, recognized as such by the compiler. This macro is defined only + * if a 64-bit type was detected and used for sph_u64. + * + * @param x the value to truncate (of type sph_u64) + */ +#define SPH_T64(x) + +/** + * Rotate a 64-bit value by a number of bits to the left. The rotate + * count must reside between 1 and 63. This macro assumes that its + * first argument fits in 64 bits (no extra bit allowed on machines where + * sph_u64 is wider); both arguments may be evaluated + * several times. This macro is defined only if a 64-bit type was detected + * and used for sph_u64. + * + * @param x the value to rotate (of type sph_u64) + * @param n the rotation count (between 1 and 63, inclusive) + */ +#define SPH_ROTL64(x, n) + +/** + * Rotate a 64-bit value by a number of bits to the left. The rotate + * count must reside between 1 and 63. This macro assumes that its + * first argument fits in 64 bits (no extra bit allowed on machines where + * sph_u64 is wider); both arguments may be evaluated + * several times. This macro is defined only if a 64-bit type was detected + * and used for sph_u64. + * + * @param x the value to rotate (of type sph_u64) + * @param n the rotation count (between 1 and 63, inclusive) + */ +#define SPH_ROTR64(x, n) + +/** + * This macro evaluates to inline or an equivalent construction, + * if available on the compilation platform, or to nothing otherwise. This + * is used to declare inline functions, for which the compiler should + * endeavour to include the code directly in the caller. Inline functions + * are typically defined in header files as replacement for macros. + */ +#define SPH_INLINE + +/** + * This macro is defined if the platform has been detected as using + * little-endian convention. This implies that the sph_u32 + * type (and the sph_u64 type also, if it is defined) has + * an exact width (i.e. exactly 32-bit, respectively 64-bit). + */ +#define SPH_LITTLE_ENDIAN + +/** + * This macro is defined if the platform has been detected as using + * big-endian convention. This implies that the sph_u32 + * type (and the sph_u64 type also, if it is defined) has + * an exact width (i.e. exactly 32-bit, respectively 64-bit). + */ +#define SPH_BIG_ENDIAN + +/** + * This macro is defined if 32-bit words (and 64-bit words, if defined) + * can be read from and written to memory efficiently in little-endian + * convention. This is the case for little-endian platforms, and also + * for the big-endian platforms which have special little-endian access + * opcodes (e.g. Ultrasparc). + */ +#define SPH_LITTLE_FAST + +/** + * This macro is defined if 32-bit words (and 64-bit words, if defined) + * can be read from and written to memory efficiently in big-endian + * convention. This is the case for little-endian platforms, and also + * for the little-endian platforms which have special big-endian access + * opcodes. + */ +#define SPH_BIG_FAST + +/** + * On some platforms, this macro is defined to an unsigned integer type + * into which pointer values may be cast. The resulting value can then + * be tested for being a multiple of 2, 4 or 8, indicating an aligned + * pointer for, respectively, 16-bit, 32-bit or 64-bit memory accesses. + */ +#define SPH_UPTR + +/** + * When defined, this macro indicates that unaligned memory accesses + * are possible with only a minor penalty, and thus should be prefered + * over strategies which first copy data to an aligned buffer. + */ +#define SPH_UNALIGNED + +/** + * Byte-swap a 32-bit word (i.e. 0x12345678 becomes + * 0x78563412). This is an inline function which resorts + * to inline assembly on some platforms, for better performance. + * + * @param x the 32-bit value to byte-swap + * @return the byte-swapped value + */ +static inline sph_u32 sph_bswap32(sph_u32 x); + +/** + * Byte-swap a 64-bit word. This is an inline function which resorts + * to inline assembly on some platforms, for better performance. This + * function is defined only if a suitable 64-bit type was found for + * sph_u64 + * + * @param x the 64-bit value to byte-swap + * @return the byte-swapped value + */ +static inline sph_u64 sph_bswap64(sph_u64 x); + +/** + * Decode a 16-bit unsigned value from memory, in little-endian convention + * (least significant byte comes first). + * + * @param src the source address + * @return the decoded value + */ +static inline unsigned sph_dec16le(const void *src); + +/** + * Encode a 16-bit unsigned value into memory, in little-endian convention + * (least significant byte comes first). + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc16le(void *dst, unsigned val); + +/** + * Decode a 16-bit unsigned value from memory, in big-endian convention + * (most significant byte comes first). + * + * @param src the source address + * @return the decoded value + */ +static inline unsigned sph_dec16be(const void *src); + +/** + * Encode a 16-bit unsigned value into memory, in big-endian convention + * (most significant byte comes first). + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc16be(void *dst, unsigned val); + +/** + * Decode a 32-bit unsigned value from memory, in little-endian convention + * (least significant byte comes first). + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u32 sph_dec32le(const void *src); + +/** + * Decode a 32-bit unsigned value from memory, in little-endian convention + * (least significant byte comes first). This function assumes that the + * source address is suitably aligned for a direct access, if the platform + * supports such things; it can thus be marginally faster than the generic + * sph_dec32le() function. + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u32 sph_dec32le_aligned(const void *src); + +/** + * Encode a 32-bit unsigned value into memory, in little-endian convention + * (least significant byte comes first). + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc32le(void *dst, sph_u32 val); + +/** + * Encode a 32-bit unsigned value into memory, in little-endian convention + * (least significant byte comes first). This function assumes that the + * destination address is suitably aligned for a direct access, if the + * platform supports such things; it can thus be marginally faster than + * the generic sph_enc32le() function. + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc32le_aligned(void *dst, sph_u32 val); + +/** + * Decode a 32-bit unsigned value from memory, in big-endian convention + * (most significant byte comes first). + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u32 sph_dec32be(const void *src); + +/** + * Decode a 32-bit unsigned value from memory, in big-endian convention + * (most significant byte comes first). This function assumes that the + * source address is suitably aligned for a direct access, if the platform + * supports such things; it can thus be marginally faster than the generic + * sph_dec32be() function. + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u32 sph_dec32be_aligned(const void *src); + +/** + * Encode a 32-bit unsigned value into memory, in big-endian convention + * (most significant byte comes first). + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc32be(void *dst, sph_u32 val); + +/** + * Encode a 32-bit unsigned value into memory, in big-endian convention + * (most significant byte comes first). This function assumes that the + * destination address is suitably aligned for a direct access, if the + * platform supports such things; it can thus be marginally faster than + * the generic sph_enc32be() function. + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc32be_aligned(void *dst, sph_u32 val); + +/** + * Decode a 64-bit unsigned value from memory, in little-endian convention + * (least significant byte comes first). This function is defined only + * if a suitable 64-bit type was detected and used for sph_u64. + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u64 sph_dec64le(const void *src); + +/** + * Decode a 64-bit unsigned value from memory, in little-endian convention + * (least significant byte comes first). This function assumes that the + * source address is suitably aligned for a direct access, if the platform + * supports such things; it can thus be marginally faster than the generic + * sph_dec64le() function. This function is defined only + * if a suitable 64-bit type was detected and used for sph_u64. + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u64 sph_dec64le_aligned(const void *src); + +/** + * Encode a 64-bit unsigned value into memory, in little-endian convention + * (least significant byte comes first). This function is defined only + * if a suitable 64-bit type was detected and used for sph_u64. + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc64le(void *dst, sph_u64 val); + +/** + * Encode a 64-bit unsigned value into memory, in little-endian convention + * (least significant byte comes first). This function assumes that the + * destination address is suitably aligned for a direct access, if the + * platform supports such things; it can thus be marginally faster than + * the generic sph_enc64le() function. This function is defined + * only if a suitable 64-bit type was detected and used for + * sph_u64. + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc64le_aligned(void *dst, sph_u64 val); + +/** + * Decode a 64-bit unsigned value from memory, in big-endian convention + * (most significant byte comes first). This function is defined only + * if a suitable 64-bit type was detected and used for sph_u64. + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u64 sph_dec64be(const void *src); + +/** + * Decode a 64-bit unsigned value from memory, in big-endian convention + * (most significant byte comes first). This function assumes that the + * source address is suitably aligned for a direct access, if the platform + * supports such things; it can thus be marginally faster than the generic + * sph_dec64be() function. This function is defined only + * if a suitable 64-bit type was detected and used for sph_u64. + * + * @param src the source address + * @return the decoded value + */ +static inline sph_u64 sph_dec64be_aligned(const void *src); + +/** + * Encode a 64-bit unsigned value into memory, in big-endian convention + * (most significant byte comes first). This function is defined only + * if a suitable 64-bit type was detected and used for sph_u64. + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc64be(void *dst, sph_u64 val); + +/** + * Encode a 64-bit unsigned value into memory, in big-endian convention + * (most significant byte comes first). This function assumes that the + * destination address is suitably aligned for a direct access, if the + * platform supports such things; it can thus be marginally faster than + * the generic sph_enc64be() function. This function is defined + * only if a suitable 64-bit type was detected and used for + * sph_u64. + * + * @param dst the destination buffer + * @param val the value to encode + */ +static inline void sph_enc64be_aligned(void *dst, sph_u64 val); + +#endif + +/* ============== END documentation block for Doxygen ============= */ + +#ifndef DOXYGEN_IGNORE + +/* + * We want to define the types "sph_u32" and "sph_u64" which hold + * unsigned values of at least, respectively, 32 and 64 bits. These + * tests should select appropriate types for most platforms. The + * macro "SPH_64" is defined if the 64-bit is supported. + */ + +#undef SPH_64 +#undef SPH_64_TRUE + +#if defined __STDC__ && __STDC_VERSION__ >= 199901L + +/* + * On C99 implementations, we can use to get an exact 64-bit + * type, if any, or otherwise use a wider type (which must exist, for + * C99 conformance). + */ + +#include + +#ifdef UINT32_MAX +typedef uint32_t sph_u32; +typedef int32_t sph_s32; +#else +typedef uint_fast32_t sph_u32; +typedef int_fast32_t sph_s32; +#endif +#if !SPH_NO_64 +#ifdef UINT64_MAX +typedef uint64_t sph_u64; +typedef int64_t sph_s64; +#else +typedef uint_fast64_t sph_u64; +typedef int_fast64_t sph_s64; +#endif +#endif + +#define SPH_C32(x) ((sph_u32)(x)) +#if !SPH_NO_64 +#define SPH_C64(x) ((sph_u64)(x)) +#define SPH_64 1 +#endif + +#else + +/* + * On non-C99 systems, we use "unsigned int" if it is wide enough, + * "unsigned long" otherwise. This supports all "reasonable" architectures. + * We have to be cautious: pre-C99 preprocessors handle constants + * differently in '#if' expressions. Hence the shifts to test UINT_MAX. + */ + +#if ((UINT_MAX >> 11) >> 11) >= 0x3FF + +typedef unsigned int sph_u32; +typedef int sph_s32; + +#define SPH_C32(x) ((sph_u32)(x ## U)) + +#else + +typedef unsigned long sph_u32; +typedef long sph_s32; + +#define SPH_C32(x) ((sph_u32)(x ## UL)) + +#endif + +#if !SPH_NO_64 + +/* + * We want a 64-bit type. We use "unsigned long" if it is wide enough (as + * is common on 64-bit architectures such as AMD64, Alpha or Sparcv9), + * "unsigned long long" otherwise, if available. We use ULLONG_MAX to + * test whether "unsigned long long" is available; we also know that + * gcc features this type, even if the libc header do not know it. + */ + +#if ((ULONG_MAX >> 31) >> 31) >= 3 + +typedef unsigned long sph_u64; +typedef long sph_s64; + +#define SPH_C64(x) ((sph_u64)(x ## UL)) + +#define SPH_64 1 + +#elif ((ULLONG_MAX >> 31) >> 31) >= 3 || defined __GNUC__ + +typedef unsigned long long sph_u64; +typedef long long sph_s64; + +#define SPH_C64(x) ((sph_u64)(x ## ULL)) + +#define SPH_64 1 + +#else + +/* + * No 64-bit type... + */ + +#endif + +#endif + +#endif + +/* + * If the "unsigned long" type has length 64 bits or more, then this is + * a "true" 64-bit architectures. This is also true with Visual C on + * amd64, even though the "long" type is limited to 32 bits. + */ +#if SPH_64 && (((ULONG_MAX >> 31) >> 31) >= 3 || defined _M_X64) +#define SPH_64_TRUE 1 +#endif + +/* + * Implementation note: some processors have specific opcodes to perform + * a rotation. Recent versions of gcc recognize the expression above and + * use the relevant opcodes, when appropriate. + */ + +#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))) + +#if SPH_64 + +#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))) + +#endif + +#ifndef DOXYGEN_IGNORE +/* + * Define SPH_INLINE to be an "inline" qualifier, if available. We define + * some small macro-like functions which benefit greatly from being inlined. + */ +#if (defined __STDC__ && __STDC_VERSION__ >= 199901L) || defined __GNUC__ +#define SPH_INLINE inline +#elif defined _MSC_VER +#define SPH_INLINE __inline +#else +#define SPH_INLINE +#endif +#endif + +/* + * We define some macros which qualify the architecture. These macros + * may be explicit set externally (e.g. as compiler parameters). The + * code below sets those macros if they are not already defined. + * + * Most macros are boolean, thus evaluate to either zero or non-zero. + * The SPH_UPTR macro is special, in that it evaluates to a C type, + * or is not defined. + * + * SPH_UPTR if defined: unsigned type to cast pointers into + * + * SPH_UNALIGNED non-zero if unaligned accesses are efficient + * SPH_LITTLE_ENDIAN non-zero if architecture is known to be little-endian + * SPH_BIG_ENDIAN non-zero if architecture is known to be big-endian + * SPH_LITTLE_FAST non-zero if little-endian decoding is fast + * SPH_BIG_FAST non-zero if big-endian decoding is fast + * + * If SPH_UPTR is defined, then encoding and decoding of 32-bit and 64-bit + * values will try to be "smart". Either SPH_LITTLE_ENDIAN or SPH_BIG_ENDIAN + * _must_ be non-zero in those situations. The 32-bit and 64-bit types + * _must_ also have an exact width. + * + * SPH_SPARCV9_GCC_32 UltraSPARC-compatible with gcc, 32-bit mode + * SPH_SPARCV9_GCC_64 UltraSPARC-compatible with gcc, 64-bit mode + * SPH_SPARCV9_GCC UltraSPARC-compatible with gcc + * SPH_I386_GCC x86-compatible (32-bit) with gcc + * SPH_I386_MSVC x86-compatible (32-bit) with Microsoft Visual C + * SPH_AMD64_GCC x86-compatible (64-bit) with gcc + * SPH_AMD64_MSVC x86-compatible (64-bit) with Microsoft Visual C + * SPH_PPC32_GCC PowerPC, 32-bit, with gcc + * SPH_PPC64_GCC PowerPC, 64-bit, with gcc + * + * TODO: enhance automatic detection, for more architectures and compilers. + * Endianness is the most important. SPH_UNALIGNED and SPH_UPTR help with + * some very fast functions (e.g. MD4) when using unaligned input data. + * The CPU-specific-with-GCC macros are useful only for inline assembly, + * normally restrained to this header file. + */ + +/* + * 32-bit x86, aka "i386 compatible". + */ +#if defined __i386__ || defined _M_IX86 + +#define SPH_DETECT_UNALIGNED 1 +#define SPH_DETECT_LITTLE_ENDIAN 1 +#define SPH_DETECT_UPTR sph_u32 +#ifdef __GNUC__ +#define SPH_DETECT_I386_GCC 1 +#endif +#ifdef _MSC_VER +#define SPH_DETECT_I386_MSVC 1 +#endif + +/* + * 64-bit x86, hereafter known as "amd64". + */ +#elif defined __x86_64 || defined _M_X64 + +#define SPH_DETECT_UNALIGNED 1 +#define SPH_DETECT_LITTLE_ENDIAN 1 +#define SPH_DETECT_UPTR sph_u64 +#ifdef __GNUC__ +#define SPH_DETECT_AMD64_GCC 1 +#endif +#ifdef _MSC_VER +#define SPH_DETECT_AMD64_MSVC 1 +#endif + +/* + * 64-bit Sparc architecture (implies v9). + */ +#elif ((defined __sparc__ || defined __sparc) && defined __arch64__) \ + || defined __sparcv9 + +#define SPH_DETECT_BIG_ENDIAN 1 +#define SPH_DETECT_UPTR sph_u64 +#ifdef __GNUC__ +#define SPH_DETECT_SPARCV9_GCC_64 1 +#define SPH_DETECT_LITTLE_FAST 1 +#endif + +/* + * 32-bit Sparc. + */ +#elif (defined __sparc__ || defined __sparc) \ + && !(defined __sparcv9 || defined __arch64__) + +#define SPH_DETECT_BIG_ENDIAN 1 +#define SPH_DETECT_UPTR sph_u32 +#if defined __GNUC__ && defined __sparc_v9__ +#define SPH_DETECT_SPARCV9_GCC_32 1 +#define SPH_DETECT_LITTLE_FAST 1 +#endif + +/* + * ARM, little-endian. + */ +#elif defined __arm__ && __ARMEL__ + +#define SPH_DETECT_LITTLE_ENDIAN 1 + +/* + * MIPS, little-endian. + */ +#elif MIPSEL || _MIPSEL || __MIPSEL || __MIPSEL__ + +#define SPH_DETECT_LITTLE_ENDIAN 1 + +/* + * MIPS, big-endian. + */ +#elif MIPSEB || _MIPSEB || __MIPSEB || __MIPSEB__ + +#define SPH_DETECT_BIG_ENDIAN 1 + +/* + * PowerPC. + */ +#elif defined __powerpc__ || defined __POWERPC__ || defined __ppc__ \ + || defined _ARCH_PPC + +/* + * Note: we do not declare cross-endian access to be "fast": even if + * using inline assembly, implementation should still assume that + * keeping the decoded word in a temporary is faster than decoding + * it again. + */ +#if defined __GNUC__ +#if SPH_64_TRUE +#define SPH_DETECT_PPC64_GCC 1 +#else +#define SPH_DETECT_PPC32_GCC 1 +#endif +#endif + +#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN +#define SPH_DETECT_BIG_ENDIAN 1 +#elif defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN +#define SPH_DETECT_LITTLE_ENDIAN 1 +#endif + +/* + * Itanium, 64-bit. + */ +#elif defined __ia64 || defined __ia64__ \ + || defined __itanium__ || defined _M_IA64 + +#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN +#define SPH_DETECT_BIG_ENDIAN 1 +#else +#define SPH_DETECT_LITTLE_ENDIAN 1 +#endif +#if defined __LP64__ || defined _LP64 +#define SPH_DETECT_UPTR sph_u64 +#else +#define SPH_DETECT_UPTR sph_u32 +#endif + +#endif + +#if defined SPH_DETECT_SPARCV9_GCC_32 || defined SPH_DETECT_SPARCV9_GCC_64 +#define SPH_DETECT_SPARCV9_GCC 1 +#endif + +#if defined SPH_DETECT_UNALIGNED && !defined SPH_UNALIGNED +#define SPH_UNALIGNED SPH_DETECT_UNALIGNED +#endif +#if defined SPH_DETECT_UPTR && !defined SPH_UPTR +#define SPH_UPTR SPH_DETECT_UPTR +#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 +#if defined SPH_DETECT_LITTLE_FAST && !defined SPH_LITTLE_FAST +#define SPH_LITTLE_FAST SPH_DETECT_LITTLE_FAST +#endif +#if defined SPH_DETECT_BIG_FAST && !defined SPH_BIG_FAST +#define SPH_BIG_FAST SPH_DETECT_BIG_FAST +#endif +#if defined SPH_DETECT_SPARCV9_GCC_32 && !defined SPH_SPARCV9_GCC_32 +#define SPH_SPARCV9_GCC_32 SPH_DETECT_SPARCV9_GCC_32 +#endif +#if defined SPH_DETECT_SPARCV9_GCC_64 && !defined SPH_SPARCV9_GCC_64 +#define SPH_SPARCV9_GCC_64 SPH_DETECT_SPARCV9_GCC_64 +#endif +#if defined SPH_DETECT_SPARCV9_GCC && !defined SPH_SPARCV9_GCC +#define SPH_SPARCV9_GCC SPH_DETECT_SPARCV9_GCC +#endif +#if defined SPH_DETECT_I386_GCC && !defined SPH_I386_GCC +#define SPH_I386_GCC SPH_DETECT_I386_GCC +#endif +#if defined SPH_DETECT_I386_MSVC && !defined SPH_I386_MSVC +#define SPH_I386_MSVC SPH_DETECT_I386_MSVC +#endif +#if defined SPH_DETECT_AMD64_GCC && !defined SPH_AMD64_GCC +#define SPH_AMD64_GCC SPH_DETECT_AMD64_GCC +#endif +#if defined SPH_DETECT_AMD64_MSVC && !defined SPH_AMD64_MSVC +#define SPH_AMD64_MSVC SPH_DETECT_AMD64_MSVC +#endif +#if defined SPH_DETECT_PPC32_GCC && !defined SPH_PPC32_GCC +#define SPH_PPC32_GCC SPH_DETECT_PPC32_GCC +#endif +#if defined SPH_DETECT_PPC64_GCC && !defined SPH_PPC64_GCC +#define SPH_PPC64_GCC SPH_DETECT_PPC64_GCC +#endif + +#if SPH_LITTLE_ENDIAN && !defined SPH_LITTLE_FAST +#define SPH_LITTLE_FAST 1 +#endif +#if SPH_BIG_ENDIAN && !defined SPH_BIG_FAST +#define SPH_BIG_FAST 1 +#endif + +#if defined SPH_UPTR && !(SPH_LITTLE_ENDIAN || SPH_BIG_ENDIAN) +#error SPH_UPTR defined, but endianness is not known. +#endif + +#if SPH_I386_GCC && !SPH_NO_ASM + +/* + * On x86 32-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit + * values. + */ + +static SPH_INLINE sph_u32 +sph_bswap32(sph_u32 x) +{ + __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); + return x; +} + +#if SPH_64 + +static SPH_INLINE sph_u64 +sph_bswap64(sph_u64 x) +{ + return ((sph_u64)sph_bswap32((sph_u32)x) << 32) + | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); +} + +#endif + +#elif SPH_AMD64_GCC && !SPH_NO_ASM + +/* + * On x86 64-bit, with gcc, we use the bswapl opcode to byte-swap 32-bit + * and 64-bit values. + */ + +static SPH_INLINE sph_u32 +sph_bswap32(sph_u32 x) +{ + __asm__ __volatile__ ("bswapl %0" : "=r" (x) : "0" (x)); + return x; +} + +#if SPH_64 + +static SPH_INLINE sph_u64 +sph_bswap64(sph_u64 x) +{ + __asm__ __volatile__ ("bswapq %0" : "=r" (x) : "0" (x)); + return x; +} + +#endif + +/* + * Disabled code. Apparently, Microsoft Visual C 2005 is smart enough + * to generate proper opcodes for endianness swapping with the pure C + * implementation below. + * + +#elif SPH_I386_MSVC && !SPH_NO_ASM + +static __inline sph_u32 __declspec(naked) __fastcall +sph_bswap32(sph_u32 x) +{ + __asm { + bswap ecx + mov eax,ecx + ret + } +} + +#if SPH_64 + +static SPH_INLINE sph_u64 +sph_bswap64(sph_u64 x) +{ + return ((sph_u64)sph_bswap32((sph_u32)x) << 32) + | (sph_u64)sph_bswap32((sph_u32)(x >> 32)); +} + +#endif + + * + * [end of disabled code] + */ + +#else + +static SPH_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; +} + +#if SPH_64 + +/** + * Byte-swap a 64-bit value. + * + * @param x the input value + * @return the byte-swapped value + */ +static SPH_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; +} + +#endif + +#endif + +#if SPH_SPARCV9_GCC && !SPH_NO_ASM + +/* + * On UltraSPARC systems, native ordering is big-endian, but it is + * possible to perform little-endian read accesses by specifying the + * address space 0x88 (ASI_PRIMARY_LITTLE). Basically, either we use + * the opcode "lda [%reg]0x88,%dst", where %reg is the register which + * contains the source address and %dst is the destination register, + * or we use "lda [%reg+imm]%asi,%dst", which uses the %asi register + * to get the address space name. The latter format is better since it + * combines an addition and the actual access in a single opcode; but + * it requires the setting (and subsequent resetting) of %asi, which is + * slow. Some operations (i.e. MD5 compression function) combine many + * successive little-endian read accesses, which may share the same + * %asi setting. The macros below contain the appropriate inline + * assembly. + */ + +#define SPH_SPARCV9_SET_ASI \ + sph_u32 sph_sparcv9_asi; \ + __asm__ __volatile__ ( \ + "rd %%asi,%0\n\twr %%g0,0x88,%%asi" : "=r" (sph_sparcv9_asi)); + +#define SPH_SPARCV9_RESET_ASI \ + __asm__ __volatile__ ("wr %%g0,%0,%%asi" : : "r" (sph_sparcv9_asi)); + +#define SPH_SPARCV9_DEC32LE(base, idx) ({ \ + sph_u32 sph_sparcv9_tmp; \ + __asm__ __volatile__ ("lda [%1+" #idx "*4]%%asi,%0" \ + : "=r" (sph_sparcv9_tmp) : "r" (base)); \ + sph_sparcv9_tmp; \ + }) + +#endif + +static SPH_INLINE void +sph_enc16be(void *dst, unsigned val) +{ + ((unsigned char *)dst)[0] = (val >> 8); + ((unsigned char *)dst)[1] = val; +} + +static SPH_INLINE unsigned +sph_dec16be(const void *src) +{ + return ((unsigned)(((const unsigned char *)src)[0]) << 8) + | (unsigned)(((const unsigned char *)src)[1]); +} + +static SPH_INLINE void +sph_enc16le(void *dst, unsigned val) +{ + ((unsigned char *)dst)[0] = val; + ((unsigned char *)dst)[1] = val >> 8; +} + +static SPH_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 SPH_INLINE void +sph_enc32be(void *dst, sph_u32 val) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_LITTLE_ENDIAN + val = sph_bswap32(val); +#endif + *(sph_u32 *)dst = val; +#else + if (((SPH_UPTR)dst & 3) == 0) { +#if SPH_LITTLE_ENDIAN + val = sph_bswap32(val); +#endif + *(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 +#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 +} + +/** + * 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 SPH_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 SPH_INLINE sph_u32 +sph_dec32be(const void *src) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_LITTLE_ENDIAN + return sph_bswap32(*(const sph_u32 *)src); +#else + return *(const sph_u32 *)src; +#endif +#else + if (((SPH_UPTR)src & 3) == 0) { +#if SPH_LITTLE_ENDIAN + return sph_bswap32(*(const sph_u32 *)src); +#else + return *(const sph_u32 *)src; +#endif + } 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 +#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 +} + +/** + * 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 SPH_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 SPH_INLINE void +sph_enc32le(void *dst, sph_u32 val) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_BIG_ENDIAN + val = sph_bswap32(val); +#endif + *(sph_u32 *)dst = val; +#else + if (((SPH_UPTR)dst & 3) == 0) { +#if SPH_BIG_ENDIAN + val = sph_bswap32(val); +#endif + *(sph_u32 *)dst = 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 +#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 +} + +/** + * 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 SPH_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 SPH_INLINE sph_u32 +sph_dec32le(const void *src) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_BIG_ENDIAN + return sph_bswap32(*(const sph_u32 *)src); +#else + return *(const sph_u32 *)src; +#endif +#else + if (((SPH_UPTR)src & 3) == 0) { +#if SPH_BIG_ENDIAN +#if SPH_SPARCV9_GCC && !SPH_NO_ASM + sph_u32 tmp; + + /* + * "__volatile__" is needed here because without it, + * gcc-3.4.3 miscompiles the code and performs the + * access before the test on the address, thus triggering + * a bus error... + */ + __asm__ __volatile__ ( + "lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; +/* + * On PowerPC, this turns out not to be worth the effort: the inline + * assembly makes GCC optimizer uncomfortable, which tends to nullify + * the decoding gains. + * + * For most hash functions, using this inline assembly trick changes + * hashing speed by less than 5% and often _reduces_ it. The biggest + * gains are for MD4 (+11%) and CubeHash (+30%). For all others, it is + * less then 10%. The speed gain on CubeHash is probably due to the + * chronic shortage of registers that CubeHash endures; for the other + * functions, the generic code appears to be efficient enough already. + * +#elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM + sph_u32 tmp; + + __asm__ __volatile__ ( + "lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; + */ +#else + return sph_bswap32(*(const sph_u32 *)src); +#endif +#else + return *(const sph_u32 *)src; +#endif + } 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 +#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 +} + +/** + * 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 SPH_INLINE sph_u32 +sph_dec32le_aligned(const void *src) +{ +#if SPH_LITTLE_ENDIAN + return *(const sph_u32 *)src; +#elif SPH_BIG_ENDIAN +#if SPH_SPARCV9_GCC && !SPH_NO_ASM + sph_u32 tmp; + + __asm__ __volatile__ ("lda [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; +/* + * Not worth it generally. + * +#elif (SPH_PPC32_GCC || SPH_PPC64_GCC) && !SPH_NO_ASM + sph_u32 tmp; + + __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; + */ +#else + return sph_bswap32(*(const sph_u32 *)src); +#endif +#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 +} + +#if SPH_64 + +/** + * 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 SPH_INLINE void +sph_enc64be(void *dst, sph_u64 val) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_LITTLE_ENDIAN + val = sph_bswap64(val); +#endif + *(sph_u64 *)dst = val; +#else + if (((SPH_UPTR)dst & 7) == 0) { +#if SPH_LITTLE_ENDIAN + val = sph_bswap64(val); +#endif + *(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 +#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 +} + +/** + * 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 SPH_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 SPH_INLINE sph_u64 +sph_dec64be(const void *src) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_LITTLE_ENDIAN + return sph_bswap64(*(const sph_u64 *)src); +#else + return *(const sph_u64 *)src; +#endif +#else + if (((SPH_UPTR)src & 7) == 0) { +#if SPH_LITTLE_ENDIAN + return sph_bswap64(*(const sph_u64 *)src); +#else + return *(const sph_u64 *)src; +#endif + } 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 +#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 +} + +/** + * 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 SPH_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 SPH_INLINE void +sph_enc64le(void *dst, sph_u64 val) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_BIG_ENDIAN + val = sph_bswap64(val); +#endif + *(sph_u64 *)dst = val; +#else + if (((SPH_UPTR)dst & 7) == 0) { +#if SPH_BIG_ENDIAN + val = sph_bswap64(val); +#endif + *(sph_u64 *)dst = 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 +#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 +} + +/** + * 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 SPH_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 SPH_INLINE sph_u64 +sph_dec64le(const void *src) +{ +#if defined SPH_UPTR +#if SPH_UNALIGNED +#if SPH_BIG_ENDIAN + return sph_bswap64(*(const sph_u64 *)src); +#else + return *(const sph_u64 *)src; +#endif +#else + if (((SPH_UPTR)src & 7) == 0) { +#if SPH_BIG_ENDIAN +#if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM + sph_u64 tmp; + + __asm__ __volatile__ ( + "ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; +/* + * Not worth it generally. + * +#elif SPH_PPC32_GCC && !SPH_NO_ASM + return (sph_u64)sph_dec32le_aligned(src) + | ((sph_u64)sph_dec32le_aligned( + (const char *)src + 4) << 32); +#elif SPH_PPC64_GCC && !SPH_NO_ASM + sph_u64 tmp; + + __asm__ __volatile__ ( + "ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; + */ +#else + return sph_bswap64(*(const sph_u64 *)src); +#endif +#else + return *(const sph_u64 *)src; +#endif + } 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 +#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 +} + +/** + * 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 SPH_INLINE sph_u64 +sph_dec64le_aligned(const void *src) +{ +#if SPH_LITTLE_ENDIAN + return *(const sph_u64 *)src; +#elif SPH_BIG_ENDIAN +#if SPH_SPARCV9_GCC_64 && !SPH_NO_ASM + sph_u64 tmp; + + __asm__ __volatile__ ("ldxa [%1]0x88,%0" : "=r" (tmp) : "r" (src)); + return tmp; +/* + * Not worth it generally. + * +#elif SPH_PPC32_GCC && !SPH_NO_ASM + return (sph_u64)sph_dec32le_aligned(src) + | ((sph_u64)sph_dec32le_aligned((const char *)src + 4) << 32); +#elif SPH_PPC64_GCC && !SPH_NO_ASM + sph_u64 tmp; + + __asm__ __volatile__ ("ldbrx %0,0,%1" : "=r" (tmp) : "r" (src)); + return tmp; + */ +#else + return sph_bswap64(*(const sph_u64 *)src); +#endif +#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 + +#endif /* Doxygen excluded block */ + +#endif diff --git a/stratum/algos/sph_whirlpool.h b/stratum/algos/sph_whirlpool.h new file mode 100644 index 000000000..493b7d791 --- /dev/null +++ b/stratum/algos/sph_whirlpool.h @@ -0,0 +1,216 @@ +/* $Id: sph_whirlpool.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * WHIRLPOOL interface. + * + * WHIRLPOOL knows three variants, dubbed "WHIRLPOOL-0" (original + * version, published in 2000, studied by NESSIE), "WHIRLPOOL-1" + * (first revision, 2001, with a new S-box) and "WHIRLPOOL" (current + * version, 2003, with a new diffusion matrix, also described as "plain + * WHIRLPOOL"). All three variants are implemented here. + * + * The original WHIRLPOOL (i.e. WHIRLPOOL-0) was published in: P. S. L. + * M. Barreto, V. Rijmen, "The Whirlpool Hashing Function", First open + * NESSIE Workshop, Leuven, Belgium, November 13--14, 2000. + * + * The current WHIRLPOOL specification and a reference implementation + * can be found on the WHIRLPOOL web page: + * http://paginas.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html + * + * ==========================(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_whirlpool.h + * @author Thomas Pornin + */ + +#ifndef SPH_WHIRLPOOL_H__ +#define SPH_WHIRLPOOL_H__ + +#include +#include "sph_types.h" +#ifdef __cplusplus +extern "C"{ +#endif + +#if SPH_64 + +/** + * Output size (in bits) for WHIRLPOOL. + */ +#define SPH_SIZE_whirlpool 512 + +/** + * Output size (in bits) for WHIRLPOOL-0. + */ +#define SPH_SIZE_whirlpool0 512 + +/** + * Output size (in bits) for WHIRLPOOL-1. + */ +#define SPH_SIZE_whirlpool1 512 + +/** + * This structure is a context for WHIRLPOOL computations: it contains the + * intermediate values and some data from the last entered block. Once + * a WHIRLPOOL computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running WHIRLPOOL computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + sph_u64 state[8]; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_whirlpool_context; + +/** + * Initialize a WHIRLPOOL context. This process performs no memory allocation. + * + * @param cc the WHIRLPOOL context (pointer to a + * sph_whirlpool_context) + */ +void sph_whirlpool_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). This function applies the + * plain WHIRLPOOL algorithm. + * + * @param cc the WHIRLPOOL context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_whirlpool(void *cc, const void *data, size_t len); + +/** + * Terminate the current WHIRLPOOL computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the WHIRLPOOL context + * @param dst the destination buffer + */ +void sph_whirlpool_close(void *cc, void *dst); + +/** + * WHIRLPOOL-0 uses the same structure than plain WHIRLPOOL. + */ +typedef sph_whirlpool_context sph_whirlpool0_context; + +#ifdef DOXYGEN_IGNORE +/** + * Initialize a WHIRLPOOL-0 context. This function is identical to + * sph_whirlpool_init(). + * + * @param cc the WHIRLPOOL context (pointer to a + * sph_whirlpool0_context) + */ +void sph_whirlpool0_init(void *cc); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_whirlpool0_init sph_whirlpool_init +#endif + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). This function applies the + * WHIRLPOOL-0 algorithm. + * + * @param cc the WHIRLPOOL context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_whirlpool0(void *cc, const void *data, size_t len); + +/** + * Terminate the current WHIRLPOOL-0 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the WHIRLPOOL-0 context + * @param dst the destination buffer + */ +void sph_whirlpool0_close(void *cc, void *dst); + +/** + * WHIRLPOOL-1 uses the same structure than plain WHIRLPOOL. + */ +typedef sph_whirlpool_context sph_whirlpool1_context; + +#ifdef DOXYGEN_IGNORE +/** + * Initialize a WHIRLPOOL-1 context. This function is identical to + * sph_whirlpool_init(). + * + * @param cc the WHIRLPOOL context (pointer to a + * sph_whirlpool1_context) + */ +void sph_whirlpool1_init(void *cc); +#endif + +#ifndef DOXYGEN_IGNORE +#define sph_whirlpool1_init sph_whirlpool_init +#endif + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). This function applies the + * WHIRLPOOL-1 algorithm. + * + * @param cc the WHIRLPOOL context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_whirlpool1(void *cc, const void *data, size_t len); + +/** + * Terminate the current WHIRLPOOL-1 computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the WHIRLPOOL-1 context + * @param dst the destination buffer + */ +void sph_whirlpool1_close(void *cc, void *dst); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/stratum/algos/x20r.c b/stratum/algos/x20r.c new file mode 100644 index 000000000..67806f022 --- /dev/null +++ b/stratum/algos/x20r.c @@ -0,0 +1,210 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gost.h" +#include "common.h" + +enum Algo { + BLAKE = 0, + BMW, + GROESTL, + JH, + KECCAK, + SKEIN, + LUFFA, + CUBEHASH, + SHAVITE, + SIMD, + ECHO, + HAMSI, + FUGUE, + SHABAL, + WHIRLPOOL, + SHA512, + HAVAL, + GOST, + RADIOGATUN, + PANAMA, + HASH_FUNC_COUNT +}; + +static void getAlgoString(const uint8_t* prevblock, char *output) +{ + char *sptr = output; + + for (int j = 0; j < HASH_FUNC_COUNT; j++) { + char b = (19 - j) >> 1; // 16 ascii hex chars, reversed + uint8_t algoDigit = (j & 1) ? prevblock[b] & 0xF : prevblock[b] >> 4; + if (algoDigit >= 10) + sprintf(sptr, "%c", 'A' + (algoDigit - 10)); + else + sprintf(sptr, "%u", (uint32_t) algoDigit); + sptr++; + } + *sptr = '\0'; +} + +void x20r_hash(const char* input, char* output, uint32_t len) +{ + uint32_t hash[64/4]; + char hashOrder[HASH_FUNC_COUNT + 1] = { 0 }; + + sph_blake512_context ctx_blake; + sph_bmw512_context ctx_bmw; + sph_groestl512_context ctx_groestl; + sph_skein512_context ctx_skein; + sph_jh512_context ctx_jh; + sph_keccak512_context ctx_keccak; + sph_luffa512_context ctx_luffa; + sph_cubehash512_context ctx_cubehash; + sph_shavite512_context ctx_shavite; + sph_simd512_context ctx_simd; + sph_echo512_context ctx_echo; + sph_hamsi512_context ctx_hamsi; + sph_fugue512_context ctx_fugue; + sph_shabal512_context ctx_shabal; + sph_whirlpool_context ctx_whirlpool; + sph_sha512_context ctx_sha512; + sph_haval256_5_context ctx_haval; + sph_gost512_context ctx_gost; + sph_radiogatun64_context ctx_radiogatun; + sph_panama_context ctx_panama; + void *in = (void*) input; + int size = len; + + getAlgoString(&input[4], hashOrder); + + + for (int i = 0; i < 20; i++) + { + const char elem = hashOrder[i]; + const uint8_t algo = elem >= 'A' ? elem - 'A' + 10 : elem - '0'; + + switch (algo) { + case BLAKE: + sph_blake512_init(&ctx_blake); + sph_blake512(&ctx_blake, in, size); + sph_blake512_close(&ctx_blake, hash); + break; + case BMW: + sph_bmw512_init(&ctx_bmw); + sph_bmw512(&ctx_bmw, in, size); + sph_bmw512_close(&ctx_bmw, hash); + break; + case GROESTL: + sph_groestl512_init(&ctx_groestl); + sph_groestl512(&ctx_groestl, in, size); + sph_groestl512_close(&ctx_groestl, hash); + break; + case SKEIN: + sph_skein512_init(&ctx_skein); + sph_skein512(&ctx_skein, in, size); + sph_skein512_close(&ctx_skein, hash); + break; + case JH: + sph_jh512_init(&ctx_jh); + sph_jh512(&ctx_jh, in, size); + sph_jh512_close(&ctx_jh, hash); + break; + case KECCAK: + sph_keccak512_init(&ctx_keccak); + sph_keccak512(&ctx_keccak, in, size); + sph_keccak512_close(&ctx_keccak, hash); + break; + case LUFFA: + sph_luffa512_init(&ctx_luffa); + sph_luffa512(&ctx_luffa, in, size); + sph_luffa512_close(&ctx_luffa, hash); + break; + case CUBEHASH: + sph_cubehash512_init(&ctx_cubehash); + sph_cubehash512(&ctx_cubehash, in, size); + sph_cubehash512_close(&ctx_cubehash, hash); + break; + case SHAVITE: + sph_shavite512_init(&ctx_shavite); + sph_shavite512(&ctx_shavite, in, size); + sph_shavite512_close(&ctx_shavite, hash); + break; + case SIMD: + sph_simd512_init(&ctx_simd); + sph_simd512(&ctx_simd, in, size); + sph_simd512_close(&ctx_simd, hash); + break; + case ECHO: + sph_echo512_init(&ctx_echo); + sph_echo512(&ctx_echo, in, size); + sph_echo512_close(&ctx_echo, hash); + break; + case HAMSI: + sph_hamsi512_init(&ctx_hamsi); + sph_hamsi512(&ctx_hamsi, in, size); + sph_hamsi512_close(&ctx_hamsi, hash); + break; + case FUGUE: + sph_fugue512_init(&ctx_fugue); + sph_fugue512(&ctx_fugue, in, size); + sph_fugue512_close(&ctx_fugue, hash); + break; + case SHABAL: + sph_shabal512_init(&ctx_shabal); + sph_shabal512(&ctx_shabal, in, size); + sph_shabal512_close(&ctx_shabal, hash); + break; + case WHIRLPOOL: + sph_whirlpool_init(&ctx_whirlpool); + sph_whirlpool(&ctx_whirlpool, in, size); + sph_whirlpool_close(&ctx_whirlpool, hash); + break; + case SHA512: + sph_sha512_init(&ctx_sha512); + sph_sha512(&ctx_sha512,(const void*) in, size); + sph_sha512_close(&ctx_sha512,(void*) hash); + break; + case HAVAL: + sph_haval256_5_init(&ctx_haval); + sph_haval256_5(&ctx_haval, in, size); + sph_haval256_5_close(&ctx_haval, hash); + break; + case GOST: + sph_gost512_init(&ctx_gost); + sph_gost512(&ctx_gost, in, size); + sph_gost512_close(&ctx_gost, hash); + break; + case RADIOGATUN: + sph_radiogatun64_init(&ctx_radiogatun); + sph_radiogatun64(&ctx_radiogatun, in, size); + sph_radiogatun64_close(&ctx_radiogatun, hash); + break; + case PANAMA: + sph_panama_init(&ctx_panama); + sph_panama(&ctx_panama, in, size); + sph_panama_close(&ctx_panama, hash); + break; + } + in = (void*) hash; + size = 64; + } + memcpy(output, hash, 32); +} diff --git a/stratum/algos/x20r.h b/stratum/algos/x20r.h new file mode 100644 index 000000000..6f75b7fb9 --- /dev/null +++ b/stratum/algos/x20r.h @@ -0,0 +1,16 @@ +#ifndef X20R_H +#define X20R_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +void x20r_hash(const char* input, char* output, uint32_t len); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/config.sample/blake2b.conf b/stratum/config.sample/blake2b.conf new file mode 100644 index 000000000..91a8e04ee --- /dev/null +++ b/stratum/config.sample/blake2b.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 5777 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = blake2b +difficulty = 0.25 +max_ttf = 4000000 + diff --git a/stratum/config.sample/dedal.conf b/stratum/config.sample/dedal.conf new file mode 100644 index 000000000..e1fd01426 --- /dev/null +++ b/stratum/config.sample/dedal.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3353 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = dedal +difficulty = 1 +max_ttf = 1000000000 + diff --git a/stratum/config.sample/sha256q.conf b/stratum/config.sample/sha256q.conf new file mode 100644 index 000000000..8b4c0d171 --- /dev/null +++ b/stratum/config.sample/sha256q.conf @@ -0,0 +1,17 @@ +[TCP] +server = yaamp.com +port = 3337 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = sha256q +difficulty = 1 +max_ttf = 40000 +reconnect = 1 + diff --git a/stratum/config.sample/x20r.conf b/stratum/config.sample/x20r.conf new file mode 100644 index 000000000..bb39777a0 --- /dev/null +++ b/stratum/config.sample/x20r.conf @@ -0,0 +1,16 @@ +[TCP] +server = yaamp.com +port = 3352 +password = tu8tu5 + +[SQL] +host = yaampdb +database = yaamp +username = root +password = patofpaq + +[STRATUM] +algo = x20r +difficulty = 0.008 +max_ttf = 50000 + diff --git a/stratum/sha3/blake2b.c b/stratum/sha3/blake2b.c new file mode 100644 index 000000000..f85c97713 --- /dev/null +++ b/stratum/sha3/blake2b.c @@ -0,0 +1,196 @@ +/* + * Copyright 2009 Colin Percival, 2014 savale + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * This file was originally written by Colin Percival as part of the Tarsnap + * online backup system. + */ + +#include +#include +#include + +#include "sph_types.h" +#include "blake2b.h" + +// Cyclic right rotation. + +#ifndef ROTR64 +#define ROTR64(x, y) (((x) >> (y)) ^ ((x) << (64 - (y)))) +#endif + +// Little-endian byte access. + +#define B2B_GET64(p) \ + (((uint64_t) ((uint8_t *) (p))[0]) ^ \ + (((uint64_t) ((uint8_t *) (p))[1]) << 8) ^ \ + (((uint64_t) ((uint8_t *) (p))[2]) << 16) ^ \ + (((uint64_t) ((uint8_t *) (p))[3]) << 24) ^ \ + (((uint64_t) ((uint8_t *) (p))[4]) << 32) ^ \ + (((uint64_t) ((uint8_t *) (p))[5]) << 40) ^ \ + (((uint64_t) ((uint8_t *) (p))[6]) << 48) ^ \ + (((uint64_t) ((uint8_t *) (p))[7]) << 56)) + +// G Mixing function. + +#define B2B_G(a, b, c, d, x, y) { \ + v[a] = v[a] + v[b] + x; \ + v[d] = ROTR64(v[d] ^ v[a], 32); \ + v[c] = v[c] + v[d]; \ + v[b] = ROTR64(v[b] ^ v[c], 24); \ + v[a] = v[a] + v[b] + y; \ + v[d] = ROTR64(v[d] ^ v[a], 16); \ + v[c] = v[c] + v[d]; \ + v[b] = ROTR64(v[b] ^ v[c], 63); } + +// Initialization Vector. + +static const uint64_t blake2b_iv[8] = { + 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, + 0x3C6EF372FE94F82B, 0xA54FF53A5F1D36F1, + 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 +}; + +// Compression function. "last" flag indicates last block. + +static void blake2b_compress(blake2b_ctx *ctx, int last) +{ + const uint8_t sigma[12][16] = { + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }, + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 }, + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 }, + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 }, + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 }, + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 }, + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 }, + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 }, + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0 }, + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } + }; + int i; + uint64_t v[16], m[16]; + + for (i = 0; i < 8; i++) { // init work variables + v[i] = ctx->h[i]; + v[i + 8] = blake2b_iv[i]; + } + + v[12] ^= ctx->t[0]; // low 64 bits of offset + v[13] ^= ctx->t[1]; // high 64 bits + if (last) // last block flag set ? + v[14] = ~v[14]; + + for (i = 0; i < 16; i++) // get little-endian words + m[i] = B2B_GET64(&ctx->b[8 * i]); + + for (i = 0; i < 12; i++) { // twelve rounds + B2B_G( 0, 4, 8, 12, m[sigma[i][ 0]], m[sigma[i][ 1]]); + B2B_G( 1, 5, 9, 13, m[sigma[i][ 2]], m[sigma[i][ 3]]); + B2B_G( 2, 6, 10, 14, m[sigma[i][ 4]], m[sigma[i][ 5]]); + B2B_G( 3, 7, 11, 15, m[sigma[i][ 6]], m[sigma[i][ 7]]); + B2B_G( 0, 5, 10, 15, m[sigma[i][ 8]], m[sigma[i][ 9]]); + B2B_G( 1, 6, 11, 12, m[sigma[i][10]], m[sigma[i][11]]); + B2B_G( 2, 7, 8, 13, m[sigma[i][12]], m[sigma[i][13]]); + B2B_G( 3, 4, 9, 14, m[sigma[i][14]], m[sigma[i][15]]); + } + + for( i = 0; i < 8; ++i ) + ctx->h[i] ^= v[i] ^ v[i + 8]; +} + +// Initialize the hashing context "ctx" with optional key "key". +// 1 <= outlen <= 64 gives the digest size in bytes. +// Secret key (also <= 64 bytes) is optional (keylen = 0). + +int blake2b_init(blake2b_ctx *ctx, size_t outlen, + const void *key, size_t keylen) // (keylen=0: no key) +{ + size_t i; + + if (outlen == 0 || outlen > 64 || keylen > 64) + return -1; // illegal parameters + + for (i = 0; i < 8; i++) // state, "param block" + ctx->h[i] = blake2b_iv[i]; + ctx->h[0] ^= 0x01010000 ^ (keylen << 8) ^ outlen; + + ctx->t[0] = 0; // input count low word + ctx->t[1] = 0; // input count high word + ctx->c = 0; // pointer within buffer + ctx->outlen = outlen; + + for (i = keylen; i < 128; i++) // zero input block + ctx->b[i] = 0; + if (keylen > 0) { + blake2b_update(ctx, key, keylen); + ctx->c = 128; // at the end + } + + return 0; +} + +// Add "inlen" bytes from "in" into the hash. + +void blake2b_update(blake2b_ctx *ctx, + const void *in, size_t inlen) // data bytes +{ + size_t i; + + for (i = 0; i < inlen; i++) { + if (ctx->c == 128) { // buffer full ? + ctx->t[0] += ctx->c; // add counters + if (ctx->t[0] < ctx->c) // carry overflow ? + ctx->t[1]++; // high word + blake2b_compress(ctx, 0); // compress (not last) + ctx->c = 0; // counter to zero + } + ctx->b[ctx->c++] = ((const uint8_t *) in)[i]; + } +} + +// Generate the message digest (size given in init). +// Result placed in "out". + +void blake2b_final(blake2b_ctx *ctx, void *out) +{ + size_t i; + + ctx->t[0] += ctx->c; // mark last block offset + if (ctx->t[0] < ctx->c) // carry overflow + ctx->t[1]++; // high word + + while (ctx->c < 128) // fill up with zeros + ctx->b[ctx->c++] = 0; + blake2b_compress(ctx, 1); // final block flag = 1 + + // little endian convert and store + for (i = 0; i < ctx->outlen; i++) { + ((uint8_t *) out)[i] = + (ctx->h[i >> 3] >> (8 * (i & 7))) & 0xFF; + } +} + diff --git a/stratum/sha3/blake2b.h b/stratum/sha3/blake2b.h new file mode 100644 index 000000000..f8652c180 --- /dev/null +++ b/stratum/sha3/blake2b.h @@ -0,0 +1,41 @@ +#pragma once +#ifndef __BLAKE2B_H__ +#define __BLAKE2B_H__ + +#include +#include + +#if defined(_MSC_VER) +#include +#define inline __inline +#define ALIGN(x) __declspec(align(x)) +#else +#define ALIGN(x) __attribute__((aligned(x))) +#endif + +#if defined(_MSC_VER) || defined(__x86_64__) || defined(__x86__) +#define NATIVE_LITTLE_ENDIAN +#endif + +// state context +ALIGN(64) typedef struct { + uint8_t b[128]; // input buffer + uint64_t h[8]; // chained state + uint64_t t[2]; // total number of bytes + size_t c; // pointer for b[] + size_t outlen; // digest size +} blake2b_ctx; + +#if defined(__cplusplus) +extern "C" { +#endif + +int blake2b_init(blake2b_ctx *ctx, size_t outlen, const void *key, size_t keylen); +void blake2b_update(blake2b_ctx *ctx, const void *in, size_t inlen); +void blake2b_final(blake2b_ctx *ctx, void *out); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/stratum/sha3/haval.c b/stratum/sha3/haval.c new file mode 100644 index 000000000..84846767c --- /dev/null +++ b/stratum/sha3/haval.c @@ -0,0 +1,983 @@ +/* $Id: haval.c 227 2010-06-16 17:28:38Z tp $ */ +/* + * HAVAL implementation. + * + * The HAVAL reference paper is of questionable clarity with regards to + * some details such as endianness of bits within a byte, bytes within + * a 32-bit word, or the actual ordering of words within a stream of + * words. This implementation has been made compatible with the reference + * implementation available on: http://labs.calyptix.com/haval.php + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_haval.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_HAVAL +#define SPH_SMALL_FOOTPRINT_HAVAL 1 +#endif + +/* + * Basic definition from the reference paper. + * +#define F1(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6)) ^ ((x0) & (x1)) ^ (x0)) + * + */ + +#define F1(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & ((x0) ^ (x4))) ^ ((x2) & (x5)) ^ ((x3) & (x6)) ^ (x0)) + +/* + * Basic definition from the reference paper. + * +#define F2(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x2) & (x3)) ^ ((x2) & (x4) & (x5)) ^ ((x1) & (x2)) \ + ^ ((x1) & (x4)) ^ ((x2) & (x6)) ^ ((x3) & (x5)) \ + ^ ((x4) & (x5)) ^ ((x0) & (x2)) ^ (x0)) + * + */ + +#define F2(x6, x5, x4, x3, x2, x1, x0) \ + (((x2) & (((x1) & ~(x3)) ^ ((x4) & (x5)) ^ (x6) ^ (x0))) \ + ^ ((x4) & ((x1) ^ (x5))) ^ ((x3 & (x5)) ^ (x0))) + +/* + * Basic definition from the reference paper. + * +#define F3(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x2) & (x3)) ^ ((x1) & (x4)) ^ ((x2) & (x5)) \ + ^ ((x3) & (x6)) ^ ((x0) & (x3)) ^ (x0)) + * + */ + +#define F3(x6, x5, x4, x3, x2, x1, x0) \ + (((x3) & (((x1) & (x2)) ^ (x6) ^ (x0))) \ + ^ ((x1) & (x4)) ^ ((x2) & (x5)) ^ (x0)) + +/* + * Basic definition from the reference paper. + * +#define F4(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x2) & (x3)) ^ ((x2) & (x4) & (x5)) ^ ((x3) & (x4) & (x6)) \ + ^ ((x1) & (x4)) ^ ((x2) & (x6)) ^ ((x3) & (x4)) ^ ((x3) & (x5)) \ + ^ ((x3) & (x6)) ^ ((x4) & (x5)) ^ ((x4) & (x6)) ^ ((x0) & (x4)) ^ (x0)) + * + */ + +#define F4(x6, x5, x4, x3, x2, x1, x0) \ + (((x3) & (((x1) & (x2)) ^ ((x4) | (x6)) ^ (x5))) \ + ^ ((x4) & ((~(x2) & (x5)) ^ (x1) ^ (x6) ^ (x0))) \ + ^ ((x2) & (x6)) ^ (x0)) + +/* + * Basic definition from the reference paper. + * +#define F5(x6, x5, x4, x3, x2, x1, x0) \ + (((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6)) \ + ^ ((x0) & (x1) & (x2) & (x3)) ^ ((x0) & (x5)) ^ (x0)) + * + */ + +#define F5(x6, x5, x4, x3, x2, x1, x0) \ + (((x0) & ~(((x1) & (x2) & (x3)) ^ (x5))) \ + ^ ((x1) & (x4)) ^ ((x2) & (x5)) ^ ((x3) & (x6))) + +/* + * The macros below integrate the phi() permutations, depending on the + * pass and the total number of passes. + */ + +#define FP3_1(x6, x5, x4, x3, x2, x1, x0) \ + F1(x1, x0, x3, x5, x6, x2, x4) +#define FP3_2(x6, x5, x4, x3, x2, x1, x0) \ + F2(x4, x2, x1, x0, x5, x3, x6) +#define FP3_3(x6, x5, x4, x3, x2, x1, x0) \ + F3(x6, x1, x2, x3, x4, x5, x0) + +#define FP4_1(x6, x5, x4, x3, x2, x1, x0) \ + F1(x2, x6, x1, x4, x5, x3, x0) +#define FP4_2(x6, x5, x4, x3, x2, x1, x0) \ + F2(x3, x5, x2, x0, x1, x6, x4) +#define FP4_3(x6, x5, x4, x3, x2, x1, x0) \ + F3(x1, x4, x3, x6, x0, x2, x5) +#define FP4_4(x6, x5, x4, x3, x2, x1, x0) \ + F4(x6, x4, x0, x5, x2, x1, x3) + +#define FP5_1(x6, x5, x4, x3, x2, x1, x0) \ + F1(x3, x4, x1, x0, x5, x2, x6) +#define FP5_2(x6, x5, x4, x3, x2, x1, x0) \ + F2(x6, x2, x1, x0, x3, x4, x5) +#define FP5_3(x6, x5, x4, x3, x2, x1, x0) \ + F3(x2, x6, x0, x4, x3, x1, x5) +#define FP5_4(x6, x5, x4, x3, x2, x1, x0) \ + F4(x1, x5, x3, x2, x0, x4, x6) +#define FP5_5(x6, x5, x4, x3, x2, x1, x0) \ + F5(x2, x5, x0, x6, x4, x3, x1) + +/* + * One step, for "n" passes, pass number "p" (1 <= p <= n), using + * input word number "w" and step constant "c". + */ +#define STEP(n, p, x7, x6, x5, x4, x3, x2, x1, x0, w, c) do { \ + sph_u32 t = FP ## n ## _ ## p(x6, x5, x4, x3, x2, x1, x0); \ + (x7) = SPH_T32(SPH_ROTR32(t, 7) + SPH_ROTR32((x7), 11) \ + + (w) + (c)); \ + } while (0) + +/* + * PASSy(n, in) computes pass number "y", for a total of "n", using the + * one-argument macro "in" to access input words. Current state is assumed + * to be held in variables "s0" to "s7". + */ + +#if SPH_SMALL_FOOTPRINT_HAVAL + +#define PASS1(n, in) do { \ + unsigned pass_count; \ + for (pass_count = 0; pass_count < 32; pass_count += 8) { \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, \ + in(pass_count + 0), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, \ + in(pass_count + 1), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, \ + in(pass_count + 2), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, \ + in(pass_count + 3), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, \ + in(pass_count + 4), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, \ + in(pass_count + 5), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, \ + in(pass_count + 6), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, \ + in(pass_count + 7), SPH_C32(0x00000000)); \ + } \ + } while (0) + +#define PASSG(p, n, in) do { \ + unsigned pass_count; \ + for (pass_count = 0; pass_count < 32; pass_count += 8) { \ + STEP(n, p, s7, s6, s5, s4, s3, s2, s1, s0, \ + in(MP ## p[pass_count + 0]), \ + RK ## p[pass_count + 0]); \ + STEP(n, p, s6, s5, s4, s3, s2, s1, s0, s7, \ + in(MP ## p[pass_count + 1]), \ + RK ## p[pass_count + 1]); \ + STEP(n, p, s5, s4, s3, s2, s1, s0, s7, s6, \ + in(MP ## p[pass_count + 2]), \ + RK ## p[pass_count + 2]); \ + STEP(n, p, s4, s3, s2, s1, s0, s7, s6, s5, \ + in(MP ## p[pass_count + 3]), \ + RK ## p[pass_count + 3]); \ + STEP(n, p, s3, s2, s1, s0, s7, s6, s5, s4, \ + in(MP ## p[pass_count + 4]), \ + RK ## p[pass_count + 4]); \ + STEP(n, p, s2, s1, s0, s7, s6, s5, s4, s3, \ + in(MP ## p[pass_count + 5]), \ + RK ## p[pass_count + 5]); \ + STEP(n, p, s1, s0, s7, s6, s5, s4, s3, s2, \ + in(MP ## p[pass_count + 6]), \ + RK ## p[pass_count + 6]); \ + STEP(n, p, s0, s7, s6, s5, s4, s3, s2, s1, \ + in(MP ## p[pass_count + 7]), \ + RK ## p[pass_count + 7]); \ + } \ + } while (0) + +#define PASS2(n, in) PASSG(2, n, in) +#define PASS3(n, in) PASSG(3, n, in) +#define PASS4(n, in) PASSG(4, n, in) +#define PASS5(n, in) PASSG(5, n, in) + +static const unsigned MP2[32] = { + 5, 14, 26, 18, 11, 28, 7, 16, + 0, 23, 20, 22, 1, 10, 4, 8, + 30, 3, 21, 9, 17, 24, 29, 6, + 19, 12, 15, 13, 2, 25, 31, 27 +}; + +static const unsigned MP3[32] = { + 19, 9, 4, 20, 28, 17, 8, 22, + 29, 14, 25, 12, 24, 30, 16, 26, + 31, 15, 7, 3, 1, 0, 18, 27, + 13, 6, 21, 10, 23, 11, 5, 2 +}; + +static const unsigned MP4[32] = { + 24, 4, 0, 14, 2, 7, 28, 23, + 26, 6, 30, 20, 18, 25, 19, 3, + 22, 11, 31, 21, 8, 27, 12, 9, + 1, 29, 5, 15, 17, 10, 16, 13 +}; + +static const unsigned MP5[32] = { + 27, 3, 21, 26, 17, 11, 20, 29, + 19, 0, 12, 7, 13, 8, 31, 10, + 5, 9, 14, 30, 18, 6, 28, 24, + 2, 23, 16, 22, 4, 1, 25, 15 +}; + +static const sph_u32 RK2[32] = { + SPH_C32(0x452821E6), SPH_C32(0x38D01377), + SPH_C32(0xBE5466CF), SPH_C32(0x34E90C6C), + SPH_C32(0xC0AC29B7), SPH_C32(0xC97C50DD), + SPH_C32(0x3F84D5B5), SPH_C32(0xB5470917), + SPH_C32(0x9216D5D9), SPH_C32(0x8979FB1B), + SPH_C32(0xD1310BA6), SPH_C32(0x98DFB5AC), + SPH_C32(0x2FFD72DB), SPH_C32(0xD01ADFB7), + SPH_C32(0xB8E1AFED), SPH_C32(0x6A267E96), + SPH_C32(0xBA7C9045), SPH_C32(0xF12C7F99), + SPH_C32(0x24A19947), SPH_C32(0xB3916CF7), + SPH_C32(0x0801F2E2), SPH_C32(0x858EFC16), + SPH_C32(0x636920D8), SPH_C32(0x71574E69), + SPH_C32(0xA458FEA3), SPH_C32(0xF4933D7E), + SPH_C32(0x0D95748F), SPH_C32(0x728EB658), + SPH_C32(0x718BCD58), SPH_C32(0x82154AEE), + SPH_C32(0x7B54A41D), SPH_C32(0xC25A59B5) +}; + +static const sph_u32 RK3[32] = { + SPH_C32(0x9C30D539), SPH_C32(0x2AF26013), + SPH_C32(0xC5D1B023), SPH_C32(0x286085F0), + SPH_C32(0xCA417918), SPH_C32(0xB8DB38EF), + SPH_C32(0x8E79DCB0), SPH_C32(0x603A180E), + SPH_C32(0x6C9E0E8B), SPH_C32(0xB01E8A3E), + SPH_C32(0xD71577C1), SPH_C32(0xBD314B27), + SPH_C32(0x78AF2FDA), SPH_C32(0x55605C60), + SPH_C32(0xE65525F3), SPH_C32(0xAA55AB94), + SPH_C32(0x57489862), SPH_C32(0x63E81440), + SPH_C32(0x55CA396A), SPH_C32(0x2AAB10B6), + SPH_C32(0xB4CC5C34), SPH_C32(0x1141E8CE), + SPH_C32(0xA15486AF), SPH_C32(0x7C72E993), + SPH_C32(0xB3EE1411), SPH_C32(0x636FBC2A), + SPH_C32(0x2BA9C55D), SPH_C32(0x741831F6), + SPH_C32(0xCE5C3E16), SPH_C32(0x9B87931E), + SPH_C32(0xAFD6BA33), SPH_C32(0x6C24CF5C) +}; + +static const sph_u32 RK4[32] = { + SPH_C32(0x7A325381), SPH_C32(0x28958677), + SPH_C32(0x3B8F4898), SPH_C32(0x6B4BB9AF), + SPH_C32(0xC4BFE81B), SPH_C32(0x66282193), + SPH_C32(0x61D809CC), SPH_C32(0xFB21A991), + SPH_C32(0x487CAC60), SPH_C32(0x5DEC8032), + SPH_C32(0xEF845D5D), SPH_C32(0xE98575B1), + SPH_C32(0xDC262302), SPH_C32(0xEB651B88), + SPH_C32(0x23893E81), SPH_C32(0xD396ACC5), + SPH_C32(0x0F6D6FF3), SPH_C32(0x83F44239), + SPH_C32(0x2E0B4482), SPH_C32(0xA4842004), + SPH_C32(0x69C8F04A), SPH_C32(0x9E1F9B5E), + SPH_C32(0x21C66842), SPH_C32(0xF6E96C9A), + SPH_C32(0x670C9C61), SPH_C32(0xABD388F0), + SPH_C32(0x6A51A0D2), SPH_C32(0xD8542F68), + SPH_C32(0x960FA728), SPH_C32(0xAB5133A3), + SPH_C32(0x6EEF0B6C), SPH_C32(0x137A3BE4) +}; + +static const sph_u32 RK5[32] = { + SPH_C32(0xBA3BF050), SPH_C32(0x7EFB2A98), + SPH_C32(0xA1F1651D), SPH_C32(0x39AF0176), + SPH_C32(0x66CA593E), SPH_C32(0x82430E88), + SPH_C32(0x8CEE8619), SPH_C32(0x456F9FB4), + SPH_C32(0x7D84A5C3), SPH_C32(0x3B8B5EBE), + SPH_C32(0xE06F75D8), SPH_C32(0x85C12073), + SPH_C32(0x401A449F), SPH_C32(0x56C16AA6), + SPH_C32(0x4ED3AA62), SPH_C32(0x363F7706), + SPH_C32(0x1BFEDF72), SPH_C32(0x429B023D), + SPH_C32(0x37D0D724), SPH_C32(0xD00A1248), + SPH_C32(0xDB0FEAD3), SPH_C32(0x49F1C09B), + SPH_C32(0x075372C9), SPH_C32(0x80991B7B), + SPH_C32(0x25D479D8), SPH_C32(0xF6E8DEF7), + SPH_C32(0xE3FE501A), SPH_C32(0xB6794C3B), + SPH_C32(0x976CE0BD), SPH_C32(0x04C006BA), + SPH_C32(0xC1A94FB6), SPH_C32(0x409F60C4) +}; + +#else + +#define PASS1(n, in) do { \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in( 0), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in( 1), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in( 2), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in( 3), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in( 4), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in( 5), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in( 6), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in( 7), SPH_C32(0x00000000)); \ + \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in( 8), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in( 9), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in(10), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in(11), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in(12), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in(13), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in(14), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in(15), SPH_C32(0x00000000)); \ + \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in(16), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in(17), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in(18), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in(19), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in(20), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in(21), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in(22), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in(23), SPH_C32(0x00000000)); \ + \ + STEP(n, 1, s7, s6, s5, s4, s3, s2, s1, s0, in(24), SPH_C32(0x00000000)); \ + STEP(n, 1, s6, s5, s4, s3, s2, s1, s0, s7, in(25), SPH_C32(0x00000000)); \ + STEP(n, 1, s5, s4, s3, s2, s1, s0, s7, s6, in(26), SPH_C32(0x00000000)); \ + STEP(n, 1, s4, s3, s2, s1, s0, s7, s6, s5, in(27), SPH_C32(0x00000000)); \ + STEP(n, 1, s3, s2, s1, s0, s7, s6, s5, s4, in(28), SPH_C32(0x00000000)); \ + STEP(n, 1, s2, s1, s0, s7, s6, s5, s4, s3, in(29), SPH_C32(0x00000000)); \ + STEP(n, 1, s1, s0, s7, s6, s5, s4, s3, s2, in(30), SPH_C32(0x00000000)); \ + STEP(n, 1, s0, s7, s6, s5, s4, s3, s2, s1, in(31), SPH_C32(0x00000000)); \ + } while (0) + +#define PASS2(n, in) do { \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in( 5), SPH_C32(0x452821E6)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in(14), SPH_C32(0x38D01377)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(26), SPH_C32(0xBE5466CF)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in(18), SPH_C32(0x34E90C6C)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in(11), SPH_C32(0xC0AC29B7)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(28), SPH_C32(0xC97C50DD)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in( 7), SPH_C32(0x3F84D5B5)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in(16), SPH_C32(0xB5470917)); \ + \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in( 0), SPH_C32(0x9216D5D9)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in(23), SPH_C32(0x8979FB1B)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(20), SPH_C32(0xD1310BA6)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in(22), SPH_C32(0x98DFB5AC)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in( 1), SPH_C32(0x2FFD72DB)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(10), SPH_C32(0xD01ADFB7)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in( 4), SPH_C32(0xB8E1AFED)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in( 8), SPH_C32(0x6A267E96)); \ + \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in(30), SPH_C32(0xBA7C9045)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in( 3), SPH_C32(0xF12C7F99)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(21), SPH_C32(0x24A19947)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in( 9), SPH_C32(0xB3916CF7)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in(17), SPH_C32(0x0801F2E2)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(24), SPH_C32(0x858EFC16)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in(29), SPH_C32(0x636920D8)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in( 6), SPH_C32(0x71574E69)); \ + \ + STEP(n, 2, s7, s6, s5, s4, s3, s2, s1, s0, in(19), SPH_C32(0xA458FEA3)); \ + STEP(n, 2, s6, s5, s4, s3, s2, s1, s0, s7, in(12), SPH_C32(0xF4933D7E)); \ + STEP(n, 2, s5, s4, s3, s2, s1, s0, s7, s6, in(15), SPH_C32(0x0D95748F)); \ + STEP(n, 2, s4, s3, s2, s1, s0, s7, s6, s5, in(13), SPH_C32(0x728EB658)); \ + STEP(n, 2, s3, s2, s1, s0, s7, s6, s5, s4, in( 2), SPH_C32(0x718BCD58)); \ + STEP(n, 2, s2, s1, s0, s7, s6, s5, s4, s3, in(25), SPH_C32(0x82154AEE)); \ + STEP(n, 2, s1, s0, s7, s6, s5, s4, s3, s2, in(31), SPH_C32(0x7B54A41D)); \ + STEP(n, 2, s0, s7, s6, s5, s4, s3, s2, s1, in(27), SPH_C32(0xC25A59B5)); \ + } while (0) + +#define PASS3(n, in) do { \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(19), SPH_C32(0x9C30D539)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in( 9), SPH_C32(0x2AF26013)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in( 4), SPH_C32(0xC5D1B023)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in(20), SPH_C32(0x286085F0)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in(28), SPH_C32(0xCA417918)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in(17), SPH_C32(0xB8DB38EF)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in( 8), SPH_C32(0x8E79DCB0)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in(22), SPH_C32(0x603A180E)); \ + \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(29), SPH_C32(0x6C9E0E8B)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in(14), SPH_C32(0xB01E8A3E)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in(25), SPH_C32(0xD71577C1)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in(12), SPH_C32(0xBD314B27)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in(24), SPH_C32(0x78AF2FDA)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in(30), SPH_C32(0x55605C60)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in(16), SPH_C32(0xE65525F3)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in(26), SPH_C32(0xAA55AB94)); \ + \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(31), SPH_C32(0x57489862)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in(15), SPH_C32(0x63E81440)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in( 7), SPH_C32(0x55CA396A)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in( 3), SPH_C32(0x2AAB10B6)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in( 1), SPH_C32(0xB4CC5C34)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in( 0), SPH_C32(0x1141E8CE)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in(18), SPH_C32(0xA15486AF)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in(27), SPH_C32(0x7C72E993)); \ + \ + STEP(n, 3, s7, s6, s5, s4, s3, s2, s1, s0, in(13), SPH_C32(0xB3EE1411)); \ + STEP(n, 3, s6, s5, s4, s3, s2, s1, s0, s7, in( 6), SPH_C32(0x636FBC2A)); \ + STEP(n, 3, s5, s4, s3, s2, s1, s0, s7, s6, in(21), SPH_C32(0x2BA9C55D)); \ + STEP(n, 3, s4, s3, s2, s1, s0, s7, s6, s5, in(10), SPH_C32(0x741831F6)); \ + STEP(n, 3, s3, s2, s1, s0, s7, s6, s5, s4, in(23), SPH_C32(0xCE5C3E16)); \ + STEP(n, 3, s2, s1, s0, s7, s6, s5, s4, s3, in(11), SPH_C32(0x9B87931E)); \ + STEP(n, 3, s1, s0, s7, s6, s5, s4, s3, s2, in( 5), SPH_C32(0xAFD6BA33)); \ + STEP(n, 3, s0, s7, s6, s5, s4, s3, s2, s1, in( 2), SPH_C32(0x6C24CF5C)); \ + } while (0) + +#define PASS4(n, in) do { \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in(24), SPH_C32(0x7A325381)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in( 4), SPH_C32(0x28958677)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in( 0), SPH_C32(0x3B8F4898)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(14), SPH_C32(0x6B4BB9AF)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in( 2), SPH_C32(0xC4BFE81B)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in( 7), SPH_C32(0x66282193)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(28), SPH_C32(0x61D809CC)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in(23), SPH_C32(0xFB21A991)); \ + \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in(26), SPH_C32(0x487CAC60)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in( 6), SPH_C32(0x5DEC8032)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in(30), SPH_C32(0xEF845D5D)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(20), SPH_C32(0xE98575B1)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in(18), SPH_C32(0xDC262302)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in(25), SPH_C32(0xEB651B88)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(19), SPH_C32(0x23893E81)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in( 3), SPH_C32(0xD396ACC5)); \ + \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in(22), SPH_C32(0x0F6D6FF3)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in(11), SPH_C32(0x83F44239)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in(31), SPH_C32(0x2E0B4482)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(21), SPH_C32(0xA4842004)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in( 8), SPH_C32(0x69C8F04A)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in(27), SPH_C32(0x9E1F9B5E)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(12), SPH_C32(0x21C66842)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in( 9), SPH_C32(0xF6E96C9A)); \ + \ + STEP(n, 4, s7, s6, s5, s4, s3, s2, s1, s0, in( 1), SPH_C32(0x670C9C61)); \ + STEP(n, 4, s6, s5, s4, s3, s2, s1, s0, s7, in(29), SPH_C32(0xABD388F0)); \ + STEP(n, 4, s5, s4, s3, s2, s1, s0, s7, s6, in( 5), SPH_C32(0x6A51A0D2)); \ + STEP(n, 4, s4, s3, s2, s1, s0, s7, s6, s5, in(15), SPH_C32(0xD8542F68)); \ + STEP(n, 4, s3, s2, s1, s0, s7, s6, s5, s4, in(17), SPH_C32(0x960FA728)); \ + STEP(n, 4, s2, s1, s0, s7, s6, s5, s4, s3, in(10), SPH_C32(0xAB5133A3)); \ + STEP(n, 4, s1, s0, s7, s6, s5, s4, s3, s2, in(16), SPH_C32(0x6EEF0B6C)); \ + STEP(n, 4, s0, s7, s6, s5, s4, s3, s2, s1, in(13), SPH_C32(0x137A3BE4)); \ + } while (0) + +#define PASS5(n, in) do { \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in(27), SPH_C32(0xBA3BF050)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in( 3), SPH_C32(0x7EFB2A98)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(21), SPH_C32(0xA1F1651D)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in(26), SPH_C32(0x39AF0176)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in(17), SPH_C32(0x66CA593E)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in(11), SPH_C32(0x82430E88)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(20), SPH_C32(0x8CEE8619)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(29), SPH_C32(0x456F9FB4)); \ + \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in(19), SPH_C32(0x7D84A5C3)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in( 0), SPH_C32(0x3B8B5EBE)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(12), SPH_C32(0xE06F75D8)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in( 7), SPH_C32(0x85C12073)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in(13), SPH_C32(0x401A449F)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in( 8), SPH_C32(0x56C16AA6)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(31), SPH_C32(0x4ED3AA62)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(10), SPH_C32(0x363F7706)); \ + \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in( 5), SPH_C32(0x1BFEDF72)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in( 9), SPH_C32(0x429B023D)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(14), SPH_C32(0x37D0D724)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in(30), SPH_C32(0xD00A1248)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in(18), SPH_C32(0xDB0FEAD3)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in( 6), SPH_C32(0x49F1C09B)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(28), SPH_C32(0x075372C9)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(24), SPH_C32(0x80991B7B)); \ + \ + STEP(n, 5, s7, s6, s5, s4, s3, s2, s1, s0, in( 2), SPH_C32(0x25D479D8)); \ + STEP(n, 5, s6, s5, s4, s3, s2, s1, s0, s7, in(23), SPH_C32(0xF6E8DEF7)); \ + STEP(n, 5, s5, s4, s3, s2, s1, s0, s7, s6, in(16), SPH_C32(0xE3FE501A)); \ + STEP(n, 5, s4, s3, s2, s1, s0, s7, s6, s5, in(22), SPH_C32(0xB6794C3B)); \ + STEP(n, 5, s3, s2, s1, s0, s7, s6, s5, s4, in( 4), SPH_C32(0x976CE0BD)); \ + STEP(n, 5, s2, s1, s0, s7, s6, s5, s4, s3, in( 1), SPH_C32(0x04C006BA)); \ + STEP(n, 5, s1, s0, s7, s6, s5, s4, s3, s2, in(25), SPH_C32(0xC1A94FB6)); \ + STEP(n, 5, s0, s7, s6, s5, s4, s3, s2, s1, in(15), SPH_C32(0x409F60C4)); \ + } while (0) + +#endif + +#define SAVE_STATE \ + sph_u32 u0, u1, u2, u3, u4, u5, u6, u7; \ + do { \ + u0 = s0; \ + u1 = s1; \ + u2 = s2; \ + u3 = s3; \ + u4 = s4; \ + u5 = s5; \ + u6 = s6; \ + u7 = s7; \ + } while (0) + +#define UPDATE_STATE do { \ + s0 = SPH_T32(s0 + u0); \ + s1 = SPH_T32(s1 + u1); \ + s2 = SPH_T32(s2 + u2); \ + s3 = SPH_T32(s3 + u3); \ + s4 = SPH_T32(s4 + u4); \ + s5 = SPH_T32(s5 + u5); \ + s6 = SPH_T32(s6 + u6); \ + s7 = SPH_T32(s7 + u7); \ + } while (0) + +/* + * COREn(in) performs the core HAVAL computation for "n" passes, using + * the one-argument macro "in" to access the input words. Running state + * is held in variable "s0" to "s7". + */ + +#define CORE3(in) do { \ + SAVE_STATE; \ + PASS1(3, in); \ + PASS2(3, in); \ + PASS3(3, in); \ + UPDATE_STATE; \ + } while (0) + +#define CORE4(in) do { \ + SAVE_STATE; \ + PASS1(4, in); \ + PASS2(4, in); \ + PASS3(4, in); \ + PASS4(4, in); \ + UPDATE_STATE; \ + } while (0) + +#define CORE5(in) do { \ + SAVE_STATE; \ + PASS1(5, in); \ + PASS2(5, in); \ + PASS3(5, in); \ + PASS4(5, in); \ + PASS5(5, in); \ + UPDATE_STATE; \ + } while (0) + +/* + * DSTATE declares the state variables "s0" to "s7". + */ +#define DSTATE sph_u32 s0, s1, s2, s3, s4, s5, s6, s7 + +/* + * RSTATE fills the state variables from the context "sc". + */ +#define RSTATE do { \ + s0 = sc->s0; \ + s1 = sc->s1; \ + s2 = sc->s2; \ + s3 = sc->s3; \ + s4 = sc->s4; \ + s5 = sc->s5; \ + s6 = sc->s6; \ + s7 = sc->s7; \ + } while (0) + +/* + * WSTATE updates the context "sc" from the state variables. + */ +#define WSTATE do { \ + sc->s0 = s0; \ + sc->s1 = s1; \ + sc->s2 = s2; \ + sc->s3 = s3; \ + sc->s4 = s4; \ + sc->s5 = s5; \ + sc->s6 = s6; \ + sc->s7 = s7; \ + } while (0) + +/* + * Initialize a context. "olen" is the output length, in 32-bit words + * (between 4 and 8, inclusive). "passes" is the number of passes + * (3, 4 or 5). + */ +static void +haval_init(sph_haval_context *sc, unsigned olen, unsigned passes) +{ + sc->s0 = SPH_C32(0x243F6A88); + sc->s1 = SPH_C32(0x85A308D3); + sc->s2 = SPH_C32(0x13198A2E); + sc->s3 = SPH_C32(0x03707344); + sc->s4 = SPH_C32(0xA4093822); + sc->s5 = SPH_C32(0x299F31D0); + sc->s6 = SPH_C32(0x082EFA98); + sc->s7 = SPH_C32(0xEC4E6C89); + sc->olen = olen; + sc->passes = passes; +#if SPH_64 + sc->count = 0; +#else + sc->count_high = 0; + sc->count_low = 0; +#endif + +} + +/* + * IN_PREPARE(data) contains declarations and code to prepare for + * reading input words pointed to by "data". + * INW(i) reads the word number "i" (from 0 to 31). + */ +#if SPH_LITTLE_FAST +#define IN_PREPARE(indata) const unsigned char *const load_ptr = \ + (const unsigned char *)(indata) +#define INW(i) sph_dec32le_aligned(load_ptr + 4 * (i)) +#else +#define IN_PREPARE(indata) \ + sph_u32 X_var[32]; \ + int load_index; \ + \ + for (load_index = 0; load_index < 32; load_index ++) \ + X_var[load_index] = sph_dec32le_aligned( \ + (const unsigned char *)(indata) + 4 * load_index) +#define INW(i) X_var[i] +#endif + +/* + * Mixing operation used for 128-bit output tailoring. This function + * takes the byte 0 from a0, byte 1 from a1, byte 2 from a2 and byte 3 + * from a3, and combines them into a 32-bit word, which is then rotated + * to the left by n bits. + */ +static SPH_INLINE sph_u32 +mix128(sph_u32 a0, sph_u32 a1, sph_u32 a2, sph_u32 a3, int n) +{ + sph_u32 tmp; + + tmp = (a0 & SPH_C32(0x000000FF)) + | (a1 & SPH_C32(0x0000FF00)) + | (a2 & SPH_C32(0x00FF0000)) + | (a3 & SPH_C32(0xFF000000)); + if (n > 0) + tmp = SPH_ROTL32(tmp, n); + return tmp; +} + +/* + * Mixing operation used to compute output word 0 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_0(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x01F80000)) + | (x6 & SPH_C32(0xFE000000)) + | (x7 & SPH_C32(0x0000003F)); + return SPH_ROTL32(tmp, 13); +} + +/* + * Mixing operation used to compute output word 1 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_1(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0xFE000000)) + | (x6 & SPH_C32(0x0000003F)) + | (x7 & SPH_C32(0x00000FC0)); + return SPH_ROTL32(tmp, 7); +} + +/* + * Mixing operation used to compute output word 2 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_2(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x0000003F)) + | (x6 & SPH_C32(0x00000FC0)) + | (x7 & SPH_C32(0x0007F000)); + return tmp; +} + +/* + * Mixing operation used to compute output word 3 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_3(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x00000FC0)) + | (x6 & SPH_C32(0x0007F000)) + | (x7 & SPH_C32(0x01F80000)); + return tmp >> 6; +} + +/* + * Mixing operation used to compute output word 4 for 160-bit output. + */ +static SPH_INLINE sph_u32 +mix160_4(sph_u32 x5, sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x5 & SPH_C32(0x0007F000)) + | (x6 & SPH_C32(0x01F80000)) + | (x7 & SPH_C32(0xFE000000)); + return tmp >> 12; +} + +/* + * Mixing operation used to compute output word 0 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_0(sph_u32 x6, sph_u32 x7) +{ + sph_u32 tmp; + + tmp = (x6 & SPH_C32(0xFC000000)) | (x7 & SPH_C32(0x0000001F)); + return SPH_ROTL32(tmp, 6); +} + +/* + * Mixing operation used to compute output word 1 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_1(sph_u32 x6, sph_u32 x7) +{ + return (x6 & SPH_C32(0x0000001F)) | (x7 & SPH_C32(0x000003E0)); +} + +/* + * Mixing operation used to compute output word 2 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_2(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x000003E0)) | (x7 & SPH_C32(0x0000FC00))) >> 5; +} + +/* + * Mixing operation used to compute output word 3 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_3(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x0000FC00)) | (x7 & SPH_C32(0x001F0000))) >> 10; +} + +/* + * Mixing operation used to compute output word 4 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_4(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x001F0000)) | (x7 & SPH_C32(0x03E00000))) >> 16; +} + +/* + * Mixing operation used to compute output word 5 for 192-bit output. + */ +static SPH_INLINE sph_u32 +mix192_5(sph_u32 x6, sph_u32 x7) +{ + return ((x6 & SPH_C32(0x03E00000)) | (x7 & SPH_C32(0xFC000000))) >> 21; +} + +/* + * Write out HAVAL output. The output length is tailored to the requested + * length. + */ +static void +haval_out(sph_haval_context *sc, void *dst) +{ + DSTATE; + unsigned char *buf; + + buf = dst; + RSTATE; + switch (sc->olen) { + case 4: + sph_enc32le(buf, SPH_T32(s0 + mix128(s7, s4, s5, s6, 24))); + sph_enc32le(buf + 4, SPH_T32(s1 + mix128(s6, s7, s4, s5, 16))); + sph_enc32le(buf + 8, SPH_T32(s2 + mix128(s5, s6, s7, s4, 8))); + sph_enc32le(buf + 12, SPH_T32(s3 + mix128(s4, s5, s6, s7, 0))); + break; + case 5: + sph_enc32le(buf, SPH_T32(s0 + mix160_0(s5, s6, s7))); + sph_enc32le(buf + 4, SPH_T32(s1 + mix160_1(s5, s6, s7))); + sph_enc32le(buf + 8, SPH_T32(s2 + mix160_2(s5, s6, s7))); + sph_enc32le(buf + 12, SPH_T32(s3 + mix160_3(s5, s6, s7))); + sph_enc32le(buf + 16, SPH_T32(s4 + mix160_4(s5, s6, s7))); + break; + case 6: + sph_enc32le(buf, SPH_T32(s0 + mix192_0(s6, s7))); + sph_enc32le(buf + 4, SPH_T32(s1 + mix192_1(s6, s7))); + sph_enc32le(buf + 8, SPH_T32(s2 + mix192_2(s6, s7))); + sph_enc32le(buf + 12, SPH_T32(s3 + mix192_3(s6, s7))); + sph_enc32le(buf + 16, SPH_T32(s4 + mix192_4(s6, s7))); + sph_enc32le(buf + 20, SPH_T32(s5 + mix192_5(s6, s7))); + break; + case 7: + sph_enc32le(buf, SPH_T32(s0 + ((s7 >> 27) & 0x1F))); + sph_enc32le(buf + 4, SPH_T32(s1 + ((s7 >> 22) & 0x1F))); + sph_enc32le(buf + 8, SPH_T32(s2 + ((s7 >> 18) & 0x0F))); + sph_enc32le(buf + 12, SPH_T32(s3 + ((s7 >> 13) & 0x1F))); + sph_enc32le(buf + 16, SPH_T32(s4 + ((s7 >> 9) & 0x0F))); + sph_enc32le(buf + 20, SPH_T32(s5 + ((s7 >> 4) & 0x1F))); + sph_enc32le(buf + 24, SPH_T32(s6 + ((s7 ) & 0x0F))); + break; + case 8: + sph_enc32le(buf, s0); + sph_enc32le(buf + 4, s1); + sph_enc32le(buf + 8, s2); + sph_enc32le(buf + 12, s3); + sph_enc32le(buf + 16, s4); + sph_enc32le(buf + 20, s5); + sph_enc32le(buf + 24, s6); + sph_enc32le(buf + 28, s7); + break; + } +} + +/* + * The main core functions inline the code with the COREx() macros. We + * use a helper file, included three times, which avoids code copying. + */ + +#undef PASSES +#define PASSES 3 +#include "haval_helper.c" + +#undef PASSES +#define PASSES 4 +#include "haval_helper.c" + +#undef PASSES +#define PASSES 5 +#include "haval_helper.c" + +/* ====================================================================== */ + +#define API(xxx, y) \ +void \ +sph_haval ## xxx ## _ ## y ## _init(void *cc) \ +{ \ + haval_init(cc, xxx >> 5, y); \ +} \ + \ +void \ +sph_haval ## xxx ## _ ## y (void *cc, const void *data, size_t len) \ +{ \ + haval ## y(cc, data, len); \ +} \ + \ +void \ +sph_haval ## xxx ## _ ## y ## _close(void *cc, void *dst) \ +{ \ + haval ## y ## _close(cc, 0, 0, dst); \ +} \ + \ +void \ +sph_haval ## xxx ## _ ## y ## addbits_and_close( \ + void *cc, unsigned ub, unsigned n, void *dst) \ +{ \ + haval ## y ## _close(cc, ub, n, dst); \ +} + +API(128, 3) +API(128, 4) +API(128, 5) +API(160, 3) +API(160, 4) +API(160, 5) +API(192, 3) +API(192, 4) +API(192, 5) +API(224, 3) +API(224, 4) +API(224, 5) +API(256, 3) +API(256, 4) +API(256, 5) + +#define RVAL do { \ + s0 = val[0]; \ + s1 = val[1]; \ + s2 = val[2]; \ + s3 = val[3]; \ + s4 = val[4]; \ + s5 = val[5]; \ + s6 = val[6]; \ + s7 = val[7]; \ + } while (0) + +#define WVAL do { \ + val[0] = s0; \ + val[1] = s1; \ + val[2] = s2; \ + val[3] = s3; \ + val[4] = s4; \ + val[5] = s5; \ + val[6] = s6; \ + val[7] = s7; \ + } while (0) + +#define INMSG(i) msg[i] + +/* see sph_haval.h */ +void +sph_haval_3_comp(const sph_u32 msg[32], sph_u32 val[8]) +{ + DSTATE; + + RVAL; + CORE3(INMSG); + WVAL; +} + +/* see sph_haval.h */ +void +sph_haval_4_comp(const sph_u32 msg[32], sph_u32 val[8]) +{ + DSTATE; + + RVAL; + CORE4(INMSG); + WVAL; +} + +/* see sph_haval.h */ +void +sph_haval_5_comp(const sph_u32 msg[32], sph_u32 val[8]) +{ + DSTATE; + + RVAL; + CORE5(INMSG); + WVAL; +} + +#ifdef __cplusplus +} +#endif diff --git a/stratum/sha3/haval_helper.c b/stratum/sha3/haval_helper.c index c402fc699..3c1cc2702 100644 --- a/stratum/sha3/haval_helper.c +++ b/stratum/sha3/haval_helper.c @@ -1,195 +1,190 @@ -/* $Id: haval_helper.c 218 2010-06-08 17:06:34Z tp $ */ -/* - * Helper code, included (three times !) by HAVAL implementation. - * - * TODO: try to merge this with md_helper.c. - * - * ==========================(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)============================= - * - * @author Thomas Pornin - */ - -#undef SPH_XCAT -#define SPH_XCAT(a, b) SPH_XCAT_(a, b) -#undef SPH_XCAT_ -#define SPH_XCAT_(a, b) a ## b - -static void -#ifdef SPH_UPTR -SPH_XCAT(SPH_XCAT(haval, PASSES), _short) -#else -SPH_XCAT(haval, PASSES) -#endif -(sph_haval_context *sc, const void *data, size_t len) -{ - unsigned current; - -#if SPH_64 - current = (unsigned)sc->count & 127U; -#else - current = (unsigned)sc->count_low & 127U; -#endif - while (len > 0) { - unsigned clen; -#if !SPH_64 - sph_u32 clow, clow2; -#endif - - clen = 128U - current; - if (clen > len) - clen = len; - memcpy(sc->buf + current, data, clen); - data = (const unsigned char *)data + clen; - current += clen; - len -= clen; - if (current == 128U) { - DSTATE; - IN_PREPARE(sc->buf); - - RSTATE; - SPH_XCAT(CORE, PASSES)(INW); - WSTATE; - current = 0; - } -#if SPH_64 - sc->count += clen; -#else - clow = sc->count_low; - clow2 = SPH_T32(clow + clen); - sc->count_low = clow2; - if (clow2 < clow) - sc->count_high ++; -#endif - } -} - -#ifdef SPH_UPTR -static void -SPH_XCAT(haval, PASSES)(sph_haval_context *sc, const void *data, size_t len) -{ - unsigned current; - size_t orig_len; -#if !SPH_64 - sph_u32 clow, clow2; -#endif - DSTATE; - - if (len < 256U) { - SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); - return; - } -#if SPH_64 - current = (unsigned)sc->count & 127U; -#else - current = (unsigned)sc->count_low & 127U; -#endif - if (current > 0) { - unsigned clen; - - clen = 128U - current; - SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, clen); - data = (const unsigned char *)data + clen; - len -= clen; - } -#if !SPH_UNALIGNED - if (((SPH_UPTR)data & 3U) != 0) { - SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); - return; - } -#endif - orig_len = len; - RSTATE; - while (len >= 128U) { - IN_PREPARE(data); - - SPH_XCAT(CORE, PASSES)(INW); - data = (const unsigned char *)data + 128U; - len -= 128U; - } - WSTATE; - if (len > 0) - memcpy(sc->buf, data, len); -#if SPH_64 - sc->count += (sph_u64)orig_len; -#else - clow = sc->count_low; - clow2 = SPH_T32(clow + orig_len); - sc->count_low = clow2; - if (clow2 < clow) - sc->count_high ++; - orig_len >>= 12; - orig_len >>= 10; - orig_len >>= 10; - sc->count_high += orig_len; -#endif -} -#endif - -static void -SPH_XCAT(SPH_XCAT(haval, PASSES), _close)(sph_haval_context *sc, - unsigned ub, unsigned n, void *dst) -{ - unsigned current; - DSTATE; - -#if SPH_64 - current = (unsigned)sc->count & 127U; -#else - current = (unsigned)sc->count_low & 127U; -#endif - sc->buf[current ++] = (0x01 << n) | ((ub & 0xFF) >> (8 - n)); - RSTATE; - if (current > 118U) { - memset(sc->buf + current, 0, 128U - current); - - do { - IN_PREPARE(sc->buf); - - SPH_XCAT(CORE, PASSES)(INW); - } while (0); - current = 0; - } - memset(sc->buf + current, 0, 118U - current); - sc->buf[118] = 0x01 | (PASSES << 3); - sc->buf[119] = sc->olen << 3; -#if SPH_64 - sph_enc64le_aligned(sc->buf + 120, SPH_T64(sc->count << 3)); -#else - sph_enc32le_aligned(sc->buf + 120, SPH_T32(sc->count_low << 3)); - sph_enc32le_aligned(sc->buf + 124, - SPH_T32((sc->count_high << 3) | (sc->count_low >> 29))); -#endif - do { - IN_PREPARE(sc->buf); - - SPH_XCAT(CORE, PASSES)(INW); - } while (0); - - WSTATE; - haval_out(sc, dst); - haval_init(sc, sc->olen, sc->passes); -} - +/* $Id: haval_helper.c 218 2010-06-08 17:06:34Z tp $ */ +/* + * Helper code, included (three times !) by HAVAL implementation. + * + * TODO: try to merge this with md_helper.c. + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#undef SPH_XCAT +#define SPH_XCAT(a, b) SPH_XCAT_(a, b) +#undef SPH_XCAT_ +#define SPH_XCAT_(a, b) a ## b + +static void +#ifdef SPH_UPTR +SPH_XCAT(SPH_XCAT(haval, PASSES), _short) +#else +SPH_XCAT(haval, PASSES) +#endif +(sph_haval_context *sc, const void *data, size_t len) +{ + unsigned current; + +#if SPH_64 + current = (unsigned)sc->count & 127U; +#else + current = (unsigned)sc->count_low & 127U; +#endif + while (len > 0) { + unsigned clen; +#if !SPH_64 + sph_u32 clow, clow2; +#endif + + clen = 128U - current; + if (clen > len) + clen = len; + memcpy(sc->buf + current, data, clen); + data = (const unsigned char *)data + clen; + current += clen; + len -= clen; + if (current == 128U) { + DSTATE; + IN_PREPARE(sc->buf); + RSTATE; + SPH_XCAT(CORE, PASSES)(INW); + WSTATE; + current = 0; + } +#if SPH_64 + sc->count += clen; +#else + clow = sc->count_low; + clow2 = SPH_T32(clow + clen); + sc->count_low = clow2; + if (clow2 < clow) + sc->count_high ++; +#endif + } +} + +#ifdef SPH_UPTR +static void +SPH_XCAT(haval, PASSES)(sph_haval_context *sc, const void *data, size_t len) +{ + unsigned current; + size_t orig_len; +#if !SPH_64 + sph_u32 clow, clow2; +#endif + DSTATE; + + if (len < 256U) { + SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); + return; + } +#if SPH_64 + current = (unsigned)sc->count & 127U; +#else + current = (unsigned)sc->count_low & 127U; +#endif + if (current > 0) { + unsigned clen; + clen = 128U - current; + SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 3U) != 0) { + SPH_XCAT(SPH_XCAT(haval, PASSES), _short)(sc, data, len); + return; + } +#endif + orig_len = len; + RSTATE; + while (len >= 128U) { + IN_PREPARE(data); + SPH_XCAT(CORE, PASSES)(INW); + data = (const unsigned char *)data + 128U; + len -= 128U; + } + WSTATE; + if (len > 0) + memcpy(sc->buf, data, len); +#if SPH_64 + sc->count += (sph_u64)orig_len; +#else + clow = sc->count_low; + clow2 = SPH_T32(clow + orig_len); + sc->count_low = clow2; + if (clow2 < clow) + sc->count_high ++; + orig_len >>= 12; + orig_len >>= 10; + orig_len >>= 10; + sc->count_high += orig_len; +#endif +} +#endif + +static void +SPH_XCAT(SPH_XCAT(haval, PASSES), _close)(sph_haval_context *sc, + unsigned ub, unsigned n, void *dst) +{ + unsigned current; + DSTATE; + +#if SPH_64 + current = (unsigned)sc->count & 127U; +#else + current = (unsigned)sc->count_low & 127U; +#endif + sc->buf[current ++] = (0x01 << n) | ((ub & 0xFF) >> (8 - n)); + RSTATE; + if (current > 118U) { + memset(sc->buf + current, 0, 128U - current); + + do { + IN_PREPARE(sc->buf); + SPH_XCAT(CORE, PASSES)(INW); + } while (0); + current = 0; + } + memset(sc->buf + current, 0, 118U - current); + sc->buf[118] = 0x01 | (PASSES << 3); + sc->buf[119] = sc->olen << 3; +#if SPH_64 + sph_enc64le_aligned(sc->buf + 120, SPH_T64(sc->count << 3)); +#else + sph_enc32le_aligned(sc->buf + 120, SPH_T32(sc->count_low << 3)); + sph_enc32le_aligned(sc->buf + 124, + SPH_T32((sc->count_high << 3) | (sc->count_low >> 29))); +#endif + + do { + IN_PREPARE(sc->buf); + SPH_XCAT(CORE, PASSES)(INW); + } while (0); + WSTATE; + + haval_out(sc, dst); + haval_init(sc, sc->olen, sc->passes); +} diff --git a/stratum/sha3/makefile b/stratum/sha3/makefile index ab83f61da..7a95eea30 100644 --- a/stratum/sha3/makefile +++ b/stratum/sha3/makefile @@ -6,8 +6,8 @@ LDFLAGS=-O2 SOURCES=sph_jh.c sph_blake.c sph_bmw.c sph_groestl.c sph_skein.c sph_keccak.c sph_luffa.c sph_cubehash.c sph_shavite.c \ sph_simd.c sph_echo.c sph_fugue.c sph_hamsi.c sph_shabal.c sph_whirlpool.c \ - sph_haval.c sph_hefty1.c sph_ripemd.c sph_sha2.c sph_sha2big.c sph_tiger.c \ - blake2s.c + sph_radiogatun.c sph_panama.c sph_haval.c sph_hefty1.c sph_ripemd.c sph_sha2.c sph_sha2big.c sph_tiger.c \ + blake2s.c blake2b.c OBJECTS=$(SOURCES:.c=.o) OUTPUT=libhash.a diff --git a/stratum/sha3/sph_haval.h b/stratum/sha3/sph_haval.h index 6334a9226..f5cf2093d 100644 --- a/stratum/sha3/sph_haval.h +++ b/stratum/sha3/sph_haval.h @@ -1,969 +1,976 @@ -/* $Id: sph_haval.h 218 2010-06-08 17:06:34Z tp $ */ -/** -* HAVAL interface. -* -* HAVAL is actually a family of 15 hash functions, depending on whether -* the internal computation uses 3, 4 or 5 passes, and on the output -* length, which is 128, 160, 192, 224 or 256 bits. This implementation -* provides interface functions for all 15, which internally map to -* three cores (depending on the number of passes). Note that output -* lengths other than 256 bits are not obtained by a simple truncation -* of a longer result; the requested length is encoded within the -* padding data. -* -* HAVAL was published in: Yuliang Zheng, Josef Pieprzyk and Jennifer -* Seberry: "HAVAL -- a one-way hashing algorithm with variable length -* of output", Advances in Cryptology -- AUSCRYPT'92, Lecture Notes in -* Computer Science, Vol.718, pp.83-104, Springer-Verlag, 1993. -* -* This paper, and a reference implementation, are available on the -* Calyptix web site: http://labs.calyptix.com/haval.php -* -* The HAVAL reference paper is quite unclear on the data encoding -* details, i.e. endianness (both byte order within a 32-bit word, and -* word order within a message block). This implementation has been -* made compatible with the reference implementation referenced above. -* -* @warning A collision for HAVAL-128/3 (HAVAL with three passes and -* 128-bit output) has been published; this function is thus considered -* as cryptographically broken. The status for other variants is unclear; -* use only with care. -* -* ==========================(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_haval.h -* @author Thomas Pornin -*/ - -#ifndef SPH_HAVAL_H__ -#define SPH_HAVAL_H__ - -#include -#include "sph_types.h" - -/** -* Output size (in bits) for HAVAL-128/3. -*/ -#define SPH_SIZE_haval128_3 128 - -/** -* Output size (in bits) for HAVAL-128/4. -*/ -#define SPH_SIZE_haval128_4 128 - -/** -* Output size (in bits) for HAVAL-128/5. -*/ -#define SPH_SIZE_haval128_5 128 - -/** -* Output size (in bits) for HAVAL-160/3. -*/ -#define SPH_SIZE_haval160_3 160 - -/** -* Output size (in bits) for HAVAL-160/4. -*/ -#define SPH_SIZE_haval160_4 160 - -/** -* Output size (in bits) for HAVAL-160/5. -*/ -#define SPH_SIZE_haval160_5 160 - -/** -* Output size (in bits) for HAVAL-192/3. -*/ -#define SPH_SIZE_haval192_3 192 - -/** -* Output size (in bits) for HAVAL-192/4. -*/ -#define SPH_SIZE_haval192_4 192 - -/** -* Output size (in bits) for HAVAL-192/5. -*/ -#define SPH_SIZE_haval192_5 192 - -/** -* Output size (in bits) for HAVAL-224/3. -*/ -#define SPH_SIZE_haval224_3 224 - -/** -* Output size (in bits) for HAVAL-224/4. -*/ -#define SPH_SIZE_haval224_4 224 - -/** -* Output size (in bits) for HAVAL-224/5. -*/ -#define SPH_SIZE_haval224_5 224 - -/** -* Output size (in bits) for HAVAL-256/3. -*/ -#define SPH_SIZE_haval256_3 256 - -/** -* Output size (in bits) for HAVAL-256/4. -*/ -#define SPH_SIZE_haval256_4 256 - -/** -* Output size (in bits) for HAVAL-256/5. -*/ -#define SPH_SIZE_haval256_5 256 - -/** -* This structure is a context for HAVAL computations: it contains the -* intermediate values and some data from the last entered block. Once -* a HAVAL computation has been performed, the context can be reused for -* another computation. -* -* The contents of this structure are private. A running HAVAL computation -* can be cloned by copying the context (e.g. with a simple -* memcpy()). -*/ -typedef struct { -#ifndef DOXYGEN_IGNORE -unsigned char buf[128]; /* first field, for alignment */ -sph_u32 s0, s1, s2, s3, s4, s5, s6, s7; -unsigned olen, passes; -#if SPH_64 -sph_u64 count; -#else -sph_u32 count_high, count_low; -#endif -#endif -} sph_haval_context; - -/** -* Type for a HAVAL-128/3 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval128_3_context; - -/** -* Type for a HAVAL-128/4 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval128_4_context; - -/** -* Type for a HAVAL-128/5 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval128_5_context; - -/** -* Type for a HAVAL-160/3 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval160_3_context; - -/** -* Type for a HAVAL-160/4 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval160_4_context; - -/** -* Type for a HAVAL-160/5 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval160_5_context; - -/** -* Type for a HAVAL-192/3 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval192_3_context; - -/** -* Type for a HAVAL-192/4 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval192_4_context; - -/** -* Type for a HAVAL-192/5 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval192_5_context; - -/** -* Type for a HAVAL-224/3 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval224_3_context; - -/** -* Type for a HAVAL-224/4 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval224_4_context; - -/** -* Type for a HAVAL-224/5 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval224_5_context; - -/** -* Type for a HAVAL-256/3 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval256_3_context; - -/** -* Type for a HAVAL-256/4 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval256_4_context; - -/** -* Type for a HAVAL-256/5 context (identical to the common context). -*/ -typedef sph_haval_context sph_haval256_5_context; - -/** -* Initialize the context for HAVAL-128/3. -* -* @param cc context to initialize (pointer to a -* sph_haval128_3_context structure) -*/ -void sph_haval128_3_init(void *cc); - -/** -* Process some data bytes for HAVAL-128/3. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-128/3 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval128_3(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-128/3 computation. The output buffer must be wide -* enough to accomodate the result (16 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-128/3 context -* @param dst the output buffer -*/ -void sph_haval128_3_close(void *cc, void *dst); - -/** -* Close a HAVAL-128/3 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (16 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-128/3 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval128_3_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-128/4. -* -* @param cc context to initialize (pointer to a -* sph_haval128_4_context structure) -*/ -void sph_haval128_4_init(void *cc); - -/** -* Process some data bytes for HAVAL-128/4. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-128/4 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval128_4(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-128/4 computation. The output buffer must be wide -* enough to accomodate the result (16 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-128/4 context -* @param dst the output buffer -*/ -void sph_haval128_4_close(void *cc, void *dst); - -/** -* Close a HAVAL-128/4 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (16 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-128/4 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval128_4_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-128/5. -* -* @param cc context to initialize (pointer to a -* sph_haval128_5_context structure) -*/ -void sph_haval128_5_init(void *cc); - -/** -* Process some data bytes for HAVAL-128/5. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-128/5 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval128_5(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-128/5 computation. The output buffer must be wide -* enough to accomodate the result (16 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-128/5 context -* @param dst the output buffer -*/ -void sph_haval128_5_close(void *cc, void *dst); - -/** -* Close a HAVAL-128/5 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (16 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-128/5 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval128_5_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-160/3. -* -* @param cc context to initialize (pointer to a -* sph_haval160_3_context structure) -*/ -void sph_haval160_3_init(void *cc); - -/** -* Process some data bytes for HAVAL-160/3. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-160/3 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval160_3(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-160/3 computation. The output buffer must be wide -* enough to accomodate the result (20 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-160/3 context -* @param dst the output buffer -*/ -void sph_haval160_3_close(void *cc, void *dst); - -/** -* Close a HAVAL-160/3 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (20 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-160/3 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval160_3_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-160/4. -* -* @param cc context to initialize (pointer to a -* sph_haval160_4_context structure) -*/ -void sph_haval160_4_init(void *cc); - -/** -* Process some data bytes for HAVAL-160/4. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-160/4 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval160_4(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-160/4 computation. The output buffer must be wide -* enough to accomodate the result (20 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-160/4 context -* @param dst the output buffer -*/ -void sph_haval160_4_close(void *cc, void *dst); - -/** -* Close a HAVAL-160/4 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (20 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-160/4 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval160_3_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-160/5. -* -* @param cc context to initialize (pointer to a -* sph_haval160_5_context structure) -*/ -void sph_haval160_5_init(void *cc); - -/** -* Process some data bytes for HAVAL-160/5. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-160/5 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval160_5(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-160/5 computation. The output buffer must be wide -* enough to accomodate the result (20 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-160/5 context -* @param dst the output buffer -*/ -void sph_haval160_5_close(void *cc, void *dst); - -/** -* Close a HAVAL-160/5 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (20 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-160/5 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval160_5_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-192/3. -* -* @param cc context to initialize (pointer to a -* sph_haval192_3_context structure) -*/ -void sph_haval192_3_init(void *cc); - -/** -* Process some data bytes for HAVAL-192/3. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-192/3 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval192_3(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-192/3 computation. The output buffer must be wide -* enough to accomodate the result (24 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-192/3 context -* @param dst the output buffer -*/ -void sph_haval192_3_close(void *cc, void *dst); - -/** -* Close a HAVAL-192/3 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (24 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-192/3 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval192_3_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-192/4. -* -* @param cc context to initialize (pointer to a -* sph_haval192_4_context structure) -*/ -void sph_haval192_4_init(void *cc); - -/** -* Process some data bytes for HAVAL-192/4. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-192/4 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval192_4(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-192/4 computation. The output buffer must be wide -* enough to accomodate the result (24 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-192/4 context -* @param dst the output buffer -*/ -void sph_haval192_4_close(void *cc, void *dst); - -/** -* Close a HAVAL-192/4 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (24 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-192/4 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval192_4_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-192/5. -* -* @param cc context to initialize (pointer to a -* sph_haval192_5_context structure) -*/ -void sph_haval192_5_init(void *cc); - -/** -* Process some data bytes for HAVAL-192/5. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-192/5 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval192_5(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-192/5 computation. The output buffer must be wide -* enough to accomodate the result (24 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-192/5 context -* @param dst the output buffer -*/ -void sph_haval192_5_close(void *cc, void *dst); - -/** -* Close a HAVAL-192/5 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (24 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-192/5 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval192_5_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-224/3. -* -* @param cc context to initialize (pointer to a -* sph_haval224_3_context structure) -*/ -void sph_haval224_3_init(void *cc); - -/** -* Process some data bytes for HAVAL-224/3. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-224/3 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval224_3(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-224/3 computation. The output buffer must be wide -* enough to accomodate the result (28 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-224/3 context -* @param dst the output buffer -*/ -void sph_haval224_3_close(void *cc, void *dst); - -/** -* Close a HAVAL-224/3 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (28 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-224/3 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval224_3_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-224/4. -* -* @param cc context to initialize (pointer to a -* sph_haval224_4_context structure) -*/ -void sph_haval224_4_init(void *cc); - -/** -* Process some data bytes for HAVAL-224/4. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-224/4 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval224_4(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-224/4 computation. The output buffer must be wide -* enough to accomodate the result (28 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-224/4 context -* @param dst the output buffer -*/ -void sph_haval224_4_close(void *cc, void *dst); - -/** -* Close a HAVAL-224/4 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (28 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-224/4 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval224_4_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-224/5. -* -* @param cc context to initialize (pointer to a -* sph_haval224_5_context structure) -*/ -void sph_haval224_5_init(void *cc); - -/** -* Process some data bytes for HAVAL-224/5. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-224/5 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval224_5(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-224/5 computation. The output buffer must be wide -* enough to accomodate the result (28 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-224/5 context -* @param dst the output buffer -*/ -void sph_haval224_5_close(void *cc, void *dst); - -/** -* Close a HAVAL-224/5 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (28 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-224/5 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval224_5_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-256/3. -* -* @param cc context to initialize (pointer to a -* sph_haval256_3_context structure) -*/ -void sph_haval256_3_init(void *cc); - -/** -* Process some data bytes for HAVAL-256/3. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-256/3 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval256_3(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-256/3 computation. The output buffer must be wide -* enough to accomodate the result (32 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-256/3 context -* @param dst the output buffer -*/ -void sph_haval256_3_close(void *cc, void *dst); - -/** -* Close a HAVAL-256/3 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (32 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-256/3 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval256_3_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-256/4. -* -* @param cc context to initialize (pointer to a -* sph_haval256_4_context structure) -*/ -void sph_haval256_4_init(void *cc); - -/** -* Process some data bytes for HAVAL-256/4. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-256/4 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval256_4(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-256/4 computation. The output buffer must be wide -* enough to accomodate the result (32 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-256/4 context -* @param dst the output buffer -*/ -void sph_haval256_4_close(void *cc, void *dst); - -/** -* Close a HAVAL-256/4 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (32 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-256/4 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval256_4_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Initialize the context for HAVAL-256/5. -* -* @param cc context to initialize (pointer to a -* sph_haval256_5_context structure) -*/ -void sph_haval256_5_init(void *cc); - -/** -* Process some data bytes for HAVAL-256/5. If len is 0, -* then this function does nothing. -* -* @param cc the HAVAL-256/5 context -* @param data the input data -* @param len the input data length (in bytes) -*/ -void sph_haval256_5(void *cc, const void *data, size_t len); - -/** -* Close a HAVAL-256/5 computation. The output buffer must be wide -* enough to accomodate the result (32 bytes). The context is automatically -* reinitialized. -* -* @param cc the HAVAL-256/5 context -* @param dst the output buffer -*/ -void sph_haval256_5_close(void *cc, void *dst); - -/** -* Close a HAVAL-256/5 computation. Up to 7 extra input bits may be added -* to the input message; these are the n upper bits of -* the ub byte (i.e. the first extra bit has value 128 in -* ub, the second extra bit has value 64, and so on). Other -* bits in ub are ignored. -* -* The output buffer must be wide enough to accomodate the result (32 -* bytes). The context is automatically reinitialized. -* -* @param cc the HAVAL-256/5 context -* @param ub the extra bits -* @param n the number of extra bits (0 to 7) -* @param dst the output buffer -*/ -void sph_haval256_5_addbits_and_close(void *cc, -unsigned ub, unsigned n, void *dst); - -/** -* Apply the HAVAL compression function on the provided data. The -* msg parameter contains the 32 32-bit input blocks, -* as numerical values (hence after the little-endian decoding). The -* val parameter contains the 8 32-bit input blocks for -* the compression function; the output is written in place in this -* array. This function uses three internal passes. -* -* @param msg the message block (32 values) -* @param val the function 256-bit input and output -*/ -void sph_haval_3_comp(const sph_u32 msg[32], sph_u32 val[8]); - -/** -* Apply the HAVAL compression function on the provided data. The -* msg parameter contains the 32 32-bit input blocks, -* as numerical values (hence after the little-endian decoding). The -* val parameter contains the 8 32-bit input blocks for -* the compression function; the output is written in place in this -* array. This function uses four internal passes. -* -* @param msg the message block (32 values) -* @param val the function 256-bit input and output -*/ -void sph_haval_4_comp(const sph_u32 msg[32], sph_u32 val[8]); - -/** -* Apply the HAVAL compression function on the provided data. The -* msg parameter contains the 32 32-bit input blocks, -* as numerical values (hence after the little-endian decoding). The -* val parameter contains the 8 32-bit input blocks for -* the compression function; the output is written in place in this -* array. This function uses five internal passes. -* -* @param msg the message block (32 values) -* @param val the function 256-bit input and output -*/ -void sph_haval_5_comp(const sph_u32 msg[32], sph_u32 val[8]); - -#endif +/* $Id: sph_haval.h 218 2010-06-08 17:06:34Z tp $ */ +/** + * HAVAL interface. + * + * HAVAL is actually a family of 15 hash functions, depending on whether + * the internal computation uses 3, 4 or 5 passes, and on the output + * length, which is 128, 160, 192, 224 or 256 bits. This implementation + * provides interface functions for all 15, which internally map to + * three cores (depending on the number of passes). Note that output + * lengths other than 256 bits are not obtained by a simple truncation + * of a longer result; the requested length is encoded within the + * padding data. + * + * HAVAL was published in: Yuliang Zheng, Josef Pieprzyk and Jennifer + * Seberry: "HAVAL -- a one-way hashing algorithm with variable length + * of output", Advances in Cryptology -- AUSCRYPT'92, Lecture Notes in + * Computer Science, Vol.718, pp.83-104, Springer-Verlag, 1993. + * + * This paper, and a reference implementation, are available on the + * Calyptix web site: http://labs.calyptix.com/haval.php + * + * The HAVAL reference paper is quite unclear on the data encoding + * details, i.e. endianness (both byte order within a 32-bit word, and + * word order within a message block). This implementation has been + * made compatible with the reference implementation referenced above. + * + * @warning A collision for HAVAL-128/3 (HAVAL with three passes and + * 128-bit output) has been published; this function is thus considered + * as cryptographically broken. The status for other variants is unclear; + * use only with care. + * + * ==========================(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_haval.h + * @author Thomas Pornin + */ + +#ifndef SPH_HAVAL_H__ +#define SPH_HAVAL_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for HAVAL-128/3. + */ +#define SPH_SIZE_haval128_3 128 + +/** + * Output size (in bits) for HAVAL-128/4. + */ +#define SPH_SIZE_haval128_4 128 + +/** + * Output size (in bits) for HAVAL-128/5. + */ +#define SPH_SIZE_haval128_5 128 + +/** + * Output size (in bits) for HAVAL-160/3. + */ +#define SPH_SIZE_haval160_3 160 + +/** + * Output size (in bits) for HAVAL-160/4. + */ +#define SPH_SIZE_haval160_4 160 + +/** + * Output size (in bits) for HAVAL-160/5. + */ +#define SPH_SIZE_haval160_5 160 + +/** + * Output size (in bits) for HAVAL-192/3. + */ +#define SPH_SIZE_haval192_3 192 + +/** + * Output size (in bits) for HAVAL-192/4. + */ +#define SPH_SIZE_haval192_4 192 + +/** + * Output size (in bits) for HAVAL-192/5. + */ +#define SPH_SIZE_haval192_5 192 + +/** + * Output size (in bits) for HAVAL-224/3. + */ +#define SPH_SIZE_haval224_3 224 + +/** + * Output size (in bits) for HAVAL-224/4. + */ +#define SPH_SIZE_haval224_4 224 + +/** + * Output size (in bits) for HAVAL-224/5. + */ +#define SPH_SIZE_haval224_5 224 + +/** + * Output size (in bits) for HAVAL-256/3. + */ +#define SPH_SIZE_haval256_3 256 + +/** + * Output size (in bits) for HAVAL-256/4. + */ +#define SPH_SIZE_haval256_4 256 + +/** + * Output size (in bits) for HAVAL-256/5. + */ +#define SPH_SIZE_haval256_5 256 + +/** + * This structure is a context for HAVAL computations: it contains the + * intermediate values and some data from the last entered block. Once + * a HAVAL computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running HAVAL computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[128]; /* first field, for alignment */ + sph_u32 s0, s1, s2, s3, s4, s5, s6, s7; + unsigned olen, passes; +#if SPH_64 + sph_u64 count; +#else + sph_u32 count_high, count_low; +#endif +#endif +} sph_haval_context; + +/** + * Type for a HAVAL-128/3 context (identical to the common context). + */ +typedef sph_haval_context sph_haval128_3_context; + +/** + * Type for a HAVAL-128/4 context (identical to the common context). + */ +typedef sph_haval_context sph_haval128_4_context; + +/** + * Type for a HAVAL-128/5 context (identical to the common context). + */ +typedef sph_haval_context sph_haval128_5_context; + +/** + * Type for a HAVAL-160/3 context (identical to the common context). + */ +typedef sph_haval_context sph_haval160_3_context; + +/** + * Type for a HAVAL-160/4 context (identical to the common context). + */ +typedef sph_haval_context sph_haval160_4_context; + +/** + * Type for a HAVAL-160/5 context (identical to the common context). + */ +typedef sph_haval_context sph_haval160_5_context; + +/** + * Type for a HAVAL-192/3 context (identical to the common context). + */ +typedef sph_haval_context sph_haval192_3_context; + +/** + * Type for a HAVAL-192/4 context (identical to the common context). + */ +typedef sph_haval_context sph_haval192_4_context; + +/** + * Type for a HAVAL-192/5 context (identical to the common context). + */ +typedef sph_haval_context sph_haval192_5_context; + +/** + * Type for a HAVAL-224/3 context (identical to the common context). + */ +typedef sph_haval_context sph_haval224_3_context; + +/** + * Type for a HAVAL-224/4 context (identical to the common context). + */ +typedef sph_haval_context sph_haval224_4_context; + +/** + * Type for a HAVAL-224/5 context (identical to the common context). + */ +typedef sph_haval_context sph_haval224_5_context; + +/** + * Type for a HAVAL-256/3 context (identical to the common context). + */ +typedef sph_haval_context sph_haval256_3_context; + +/** + * Type for a HAVAL-256/4 context (identical to the common context). + */ +typedef sph_haval_context sph_haval256_4_context; + +/** + * Type for a HAVAL-256/5 context (identical to the common context). + */ +typedef sph_haval_context sph_haval256_5_context; + +/** + * Initialize the context for HAVAL-128/3. + * + * @param cc context to initialize (pointer to a + * sph_haval128_3_context structure) + */ +void sph_haval128_3_init(void *cc); + +/** + * Process some data bytes for HAVAL-128/3. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-128/3 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval128_3(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-128/3 computation. The output buffer must be wide + * enough to accomodate the result (16 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-128/3 context + * @param dst the output buffer + */ +void sph_haval128_3_close(void *cc, void *dst); + +/** + * Close a HAVAL-128/3 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (16 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-128/3 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval128_3_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-128/4. + * + * @param cc context to initialize (pointer to a + * sph_haval128_4_context structure) + */ +void sph_haval128_4_init(void *cc); + +/** + * Process some data bytes for HAVAL-128/4. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-128/4 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval128_4(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-128/4 computation. The output buffer must be wide + * enough to accomodate the result (16 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-128/4 context + * @param dst the output buffer + */ +void sph_haval128_4_close(void *cc, void *dst); + +/** + * Close a HAVAL-128/4 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (16 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-128/4 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval128_4_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-128/5. + * + * @param cc context to initialize (pointer to a + * sph_haval128_5_context structure) + */ +void sph_haval128_5_init(void *cc); + +/** + * Process some data bytes for HAVAL-128/5. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-128/5 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval128_5(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-128/5 computation. The output buffer must be wide + * enough to accomodate the result (16 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-128/5 context + * @param dst the output buffer + */ +void sph_haval128_5_close(void *cc, void *dst); + +/** + * Close a HAVAL-128/5 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (16 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-128/5 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval128_5_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-160/3. + * + * @param cc context to initialize (pointer to a + * sph_haval160_3_context structure) + */ +void sph_haval160_3_init(void *cc); + +/** + * Process some data bytes for HAVAL-160/3. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-160/3 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval160_3(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-160/3 computation. The output buffer must be wide + * enough to accomodate the result (20 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-160/3 context + * @param dst the output buffer + */ +void sph_haval160_3_close(void *cc, void *dst); + +/** + * Close a HAVAL-160/3 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (20 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-160/3 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval160_3_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-160/4. + * + * @param cc context to initialize (pointer to a + * sph_haval160_4_context structure) + */ +void sph_haval160_4_init(void *cc); + +/** + * Process some data bytes for HAVAL-160/4. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-160/4 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval160_4(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-160/4 computation. The output buffer must be wide + * enough to accomodate the result (20 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-160/4 context + * @param dst the output buffer + */ +void sph_haval160_4_close(void *cc, void *dst); + +/** + * Close a HAVAL-160/4 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (20 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-160/4 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval160_3_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-160/5. + * + * @param cc context to initialize (pointer to a + * sph_haval160_5_context structure) + */ +void sph_haval160_5_init(void *cc); + +/** + * Process some data bytes for HAVAL-160/5. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-160/5 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval160_5(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-160/5 computation. The output buffer must be wide + * enough to accomodate the result (20 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-160/5 context + * @param dst the output buffer + */ +void sph_haval160_5_close(void *cc, void *dst); + +/** + * Close a HAVAL-160/5 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (20 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-160/5 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval160_5_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-192/3. + * + * @param cc context to initialize (pointer to a + * sph_haval192_3_context structure) + */ +void sph_haval192_3_init(void *cc); + +/** + * Process some data bytes for HAVAL-192/3. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-192/3 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval192_3(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-192/3 computation. The output buffer must be wide + * enough to accomodate the result (24 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-192/3 context + * @param dst the output buffer + */ +void sph_haval192_3_close(void *cc, void *dst); + +/** + * Close a HAVAL-192/3 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (24 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-192/3 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval192_3_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-192/4. + * + * @param cc context to initialize (pointer to a + * sph_haval192_4_context structure) + */ +void sph_haval192_4_init(void *cc); + +/** + * Process some data bytes for HAVAL-192/4. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-192/4 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval192_4(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-192/4 computation. The output buffer must be wide + * enough to accomodate the result (24 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-192/4 context + * @param dst the output buffer + */ +void sph_haval192_4_close(void *cc, void *dst); + +/** + * Close a HAVAL-192/4 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (24 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-192/4 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval192_4_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-192/5. + * + * @param cc context to initialize (pointer to a + * sph_haval192_5_context structure) + */ +void sph_haval192_5_init(void *cc); + +/** + * Process some data bytes for HAVAL-192/5. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-192/5 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval192_5(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-192/5 computation. The output buffer must be wide + * enough to accomodate the result (24 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-192/5 context + * @param dst the output buffer + */ +void sph_haval192_5_close(void *cc, void *dst); + +/** + * Close a HAVAL-192/5 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (24 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-192/5 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval192_5_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-224/3. + * + * @param cc context to initialize (pointer to a + * sph_haval224_3_context structure) + */ +void sph_haval224_3_init(void *cc); + +/** + * Process some data bytes for HAVAL-224/3. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-224/3 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval224_3(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-224/3 computation. The output buffer must be wide + * enough to accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-224/3 context + * @param dst the output buffer + */ +void sph_haval224_3_close(void *cc, void *dst); + +/** + * Close a HAVAL-224/3 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (28 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-224/3 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval224_3_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-224/4. + * + * @param cc context to initialize (pointer to a + * sph_haval224_4_context structure) + */ +void sph_haval224_4_init(void *cc); + +/** + * Process some data bytes for HAVAL-224/4. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-224/4 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval224_4(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-224/4 computation. The output buffer must be wide + * enough to accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-224/4 context + * @param dst the output buffer + */ +void sph_haval224_4_close(void *cc, void *dst); + +/** + * Close a HAVAL-224/4 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (28 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-224/4 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval224_4_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-224/5. + * + * @param cc context to initialize (pointer to a + * sph_haval224_5_context structure) + */ +void sph_haval224_5_init(void *cc); + +/** + * Process some data bytes for HAVAL-224/5. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-224/5 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval224_5(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-224/5 computation. The output buffer must be wide + * enough to accomodate the result (28 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-224/5 context + * @param dst the output buffer + */ +void sph_haval224_5_close(void *cc, void *dst); + +/** + * Close a HAVAL-224/5 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (28 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-224/5 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval224_5_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-256/3. + * + * @param cc context to initialize (pointer to a + * sph_haval256_3_context structure) + */ +void sph_haval256_3_init(void *cc); + +/** + * Process some data bytes for HAVAL-256/3. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-256/3 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval256_3(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-256/3 computation. The output buffer must be wide + * enough to accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-256/3 context + * @param dst the output buffer + */ +void sph_haval256_3_close(void *cc, void *dst); + +/** + * Close a HAVAL-256/3 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (32 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-256/3 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval256_3_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-256/4. + * + * @param cc context to initialize (pointer to a + * sph_haval256_4_context structure) + */ +void sph_haval256_4_init(void *cc); + +/** + * Process some data bytes for HAVAL-256/4. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-256/4 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval256_4(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-256/4 computation. The output buffer must be wide + * enough to accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-256/4 context + * @param dst the output buffer + */ +void sph_haval256_4_close(void *cc, void *dst); + +/** + * Close a HAVAL-256/4 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (32 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-256/4 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval256_4_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Initialize the context for HAVAL-256/5. + * + * @param cc context to initialize (pointer to a + * sph_haval256_5_context structure) + */ +void sph_haval256_5_init(void *cc); + +/** + * Process some data bytes for HAVAL-256/5. If len is 0, + * then this function does nothing. + * + * @param cc the HAVAL-256/5 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_haval256_5(void *cc, const void *data, size_t len); + +/** + * Close a HAVAL-256/5 computation. The output buffer must be wide + * enough to accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the HAVAL-256/5 context + * @param dst the output buffer + */ +void sph_haval256_5_close(void *cc, void *dst); + +/** + * Close a HAVAL-256/5 computation. Up to 7 extra input bits may be added + * to the input message; these are the n upper bits of + * the ub byte (i.e. the first extra bit has value 128 in + * ub, the second extra bit has value 64, and so on). Other + * bits in ub are ignored. + * + * The output buffer must be wide enough to accomodate the result (32 + * bytes). The context is automatically reinitialized. + * + * @param cc the HAVAL-256/5 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the output buffer + */ +void sph_haval256_5_addbits_and_close(void *cc, + unsigned ub, unsigned n, void *dst); + +/** + * Apply the HAVAL compression function on the provided data. The + * msg parameter contains the 32 32-bit input blocks, + * as numerical values (hence after the little-endian decoding). The + * val parameter contains the 8 32-bit input blocks for + * the compression function; the output is written in place in this + * array. This function uses three internal passes. + * + * @param msg the message block (32 values) + * @param val the function 256-bit input and output + */ +void sph_haval_3_comp(const sph_u32 msg[32], sph_u32 val[8]); + +/** + * Apply the HAVAL compression function on the provided data. The + * msg parameter contains the 32 32-bit input blocks, + * as numerical values (hence after the little-endian decoding). The + * val parameter contains the 8 32-bit input blocks for + * the compression function; the output is written in place in this + * array. This function uses four internal passes. + * + * @param msg the message block (32 values) + * @param val the function 256-bit input and output + */ +void sph_haval_4_comp(const sph_u32 msg[32], sph_u32 val[8]); + +/** + * Apply the HAVAL compression function on the provided data. The + * msg parameter contains the 32 32-bit input blocks, + * as numerical values (hence after the little-endian decoding). The + * val parameter contains the 8 32-bit input blocks for + * the compression function; the output is written in place in this + * array. This function uses five internal passes. + * + * @param msg the message block (32 values) + * @param val the function 256-bit input and output + */ +void sph_haval_5_comp(const sph_u32 msg[32], sph_u32 val[8]); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/stratum/sha3/sph_panama.c b/stratum/sha3/sph_panama.c new file mode 100644 index 000000000..0eca16a9f --- /dev/null +++ b/stratum/sha3/sph_panama.c @@ -0,0 +1,334 @@ +/* $Id: panama.c 216 2010-06-08 09:46:57Z tp $ */ +/* + * PANAMA implementation. + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_panama.h" + +#define LVAR17(b) sph_u32 \ + b ## 0, b ## 1, b ## 2, b ## 3, b ## 4, b ## 5, \ + b ## 6, b ## 7, b ## 8, b ## 9, b ## 10, b ## 11, \ + b ## 12, b ## 13, b ## 14, b ## 15, b ## 16; + +#define LVARS \ + LVAR17(a) \ + LVAR17(g) \ + LVAR17(p) \ + LVAR17(t) + +#define M17(macro) do { \ + macro( 0, 1, 2, 4); \ + macro( 1, 2, 3, 5); \ + macro( 2, 3, 4, 6); \ + macro( 3, 4, 5, 7); \ + macro( 4, 5, 6, 8); \ + macro( 5, 6, 7, 9); \ + macro( 6, 7, 8, 10); \ + macro( 7, 8, 9, 11); \ + macro( 8, 9, 10, 12); \ + macro( 9, 10, 11, 13); \ + macro(10, 11, 12, 14); \ + macro(11, 12, 13, 15); \ + macro(12, 13, 14, 16); \ + macro(13, 14, 15, 0); \ + macro(14, 15, 16, 1); \ + macro(15, 16, 0, 2); \ + macro(16, 0, 1, 3); \ + } while (0) + +#define BUPDATE1(n0, n2) do { \ + sc->buffer[ptr24][n0] ^= sc->buffer[ptr31][n2]; \ + sc->buffer[ptr31][n2] ^= INW1(n2); \ + } while (0) + +#define BUPDATE do { \ + BUPDATE1(0, 2); \ + BUPDATE1(1, 3); \ + BUPDATE1(2, 4); \ + BUPDATE1(3, 5); \ + BUPDATE1(4, 6); \ + BUPDATE1(5, 7); \ + BUPDATE1(6, 0); \ + BUPDATE1(7, 1); \ + } while (0) + +#define RSTATE(n0, n1, n2, n4) (a ## n0 = sc->state[n0]) + +#define WSTATE(n0, n1, n2, n4) (sc->state[n0] = a ## n0) + +#define GAMMA(n0, n1, n2, n4) \ + (g ## n0 = a ## n0 ^ (a ## n1 | SPH_T32(~a ## n2))) + +#define PI_ALL do { \ + p0 = g0; \ + p1 = SPH_ROTL32( g7, 1); \ + p2 = SPH_ROTL32(g14, 3); \ + p3 = SPH_ROTL32( g4, 6); \ + p4 = SPH_ROTL32(g11, 10); \ + p5 = SPH_ROTL32( g1, 15); \ + p6 = SPH_ROTL32( g8, 21); \ + p7 = SPH_ROTL32(g15, 28); \ + p8 = SPH_ROTL32( g5, 4); \ + p9 = SPH_ROTL32(g12, 13); \ + p10 = SPH_ROTL32( g2, 23); \ + p11 = SPH_ROTL32( g9, 2); \ + p12 = SPH_ROTL32(g16, 14); \ + p13 = SPH_ROTL32( g6, 27); \ + p14 = SPH_ROTL32(g13, 9); \ + p15 = SPH_ROTL32( g3, 24); \ + p16 = SPH_ROTL32(g10, 8); \ + } while (0) + +#define THETA(n0, n1, n2, n4) \ + (t ## n0 = p ## n0 ^ p ## n1 ^ p ## n4) + +#define SIGMA_ALL do { \ + a0 = t0 ^ 1; \ + a1 = t1 ^ INW2(0); \ + a2 = t2 ^ INW2(1); \ + a3 = t3 ^ INW2(2); \ + a4 = t4 ^ INW2(3); \ + a5 = t5 ^ INW2(4); \ + a6 = t6 ^ INW2(5); \ + a7 = t7 ^ INW2(6); \ + a8 = t8 ^ INW2(7); \ + a9 = t9 ^ sc->buffer[ptr16][0]; \ + a10 = t10 ^ sc->buffer[ptr16][1]; \ + a11 = t11 ^ sc->buffer[ptr16][2]; \ + a12 = t12 ^ sc->buffer[ptr16][3]; \ + a13 = t13 ^ sc->buffer[ptr16][4]; \ + a14 = t14 ^ sc->buffer[ptr16][5]; \ + a15 = t15 ^ sc->buffer[ptr16][6]; \ + a16 = t16 ^ sc->buffer[ptr16][7]; \ + } while (0) + +#define PANAMA_STEP do { \ + unsigned ptr16, ptr24, ptr31; \ + \ + ptr24 = (ptr0 - 8) & 31; \ + ptr31 = (ptr0 - 1) & 31; \ + BUPDATE; \ + M17(GAMMA); \ + PI_ALL; \ + M17(THETA); \ + ptr16 = ptr0 ^ 16; \ + SIGMA_ALL; \ + ptr0 = ptr31; \ + } while (0) + +/* + * These macros are used to compute + */ +#define INC0 1 +#define INC1 2 +#define INC2 3 +#define INC3 4 +#define INC4 5 +#define INC5 6 +#define INC6 7 +#define INC7 8 + +/* + * Push data by blocks of 32 bytes. "pbuf" must be 32-bit aligned. Each + * iteration processes 32 data bytes; "num" contains the number of + * iterations. + */ +static void +panama_push(sph_panama_context *sc, const unsigned char *pbuf, size_t num) +{ + LVARS + unsigned ptr0; +#if SPH_LITTLE_FAST +#define INW1(i) sph_dec32le_aligned(pbuf + 4 * (i)) +#else + sph_u32 X_var[8]; +#define INW1(i) X_var[i] +#endif +#define INW2(i) INW1(i) + + M17(RSTATE); + ptr0 = sc->buffer_ptr; + while (num -- > 0) { +#if !SPH_LITTLE_FAST + int i; + + for (i = 0; i < 8; i ++) + X_var[i] = sph_dec32le_aligned(pbuf + 4 * (i)); +#endif + PANAMA_STEP; + pbuf = (const unsigned char *)pbuf + 32; + } + M17(WSTATE); + sc->buffer_ptr = ptr0; + +#undef INW1 +#undef INW2 +} + +/* + * Perform the "pull" operation repeatedly ("num" times). The hash output + * will be extracted from the state afterwards. + */ +static void +panama_pull(sph_panama_context *sc, unsigned num) +{ + LVARS + unsigned ptr0; +#define INW1(i) INW_H1(INC ## i) +#define INW_H1(i) INW_H2(i) +#define INW_H2(i) a ## i +#define INW2(i) sc->buffer[ptr4][i] + + M17(RSTATE); + ptr0 = sc->buffer_ptr; + while (num -- > 0) { + unsigned ptr4; + + ptr4 = (ptr0 + 4) & 31; + PANAMA_STEP; + } + M17(WSTATE); + +#undef INW1 +#undef INW_H1 +#undef INW_H2 +#undef INW2 +} + +/* see sph_panama.h */ +void +sph_panama_init(void *cc) +{ + sph_panama_context *sc; + + sc = cc; + /* + * This is not completely conformant, but "it will work + * everywhere". Initial state consists of zeroes everywhere. + * Conceptually, the sph_u32 type may have padding bits which + * must not be set to 0; but such an architecture remains to + * be seen. + */ + sc->data_ptr = 0; + memset(sc->buffer, 0, sizeof sc->buffer); + sc->buffer_ptr = 0; + memset(sc->state, 0, sizeof sc->state); +} + +#ifdef SPH_UPTR +static void +panama_short(void *cc, const void *data, size_t len) +#else +void +sph_panama(void *cc, const void *data, size_t len) +#endif +{ + sph_panama_context *sc; + unsigned current; + + sc = cc; + current = sc->data_ptr; + while (len > 0) { + unsigned clen; + + clen = (sizeof sc->data) - current; + if (clen > len) + clen = len; + memcpy(sc->data + current, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + current += clen; + if (current == sizeof sc->data) { + current = 0; + panama_push(sc, sc->data, 1); + } + } + sc->data_ptr = current; +} + +#ifdef SPH_UPTR +/* see sph_panama.h */ +void +sph_panama(void *cc, const void *data, size_t len) +{ + sph_panama_context *sc; + unsigned current; + size_t rlen; + + if (len < (2 * sizeof sc->data)) { + panama_short(cc, data, len); + return; + } + sc = cc; + current = sc->data_ptr; + if (current > 0) { + unsigned t; + + t = (sizeof sc->data) - current; + panama_short(sc, data, t); + data = (const unsigned char *)data + t; + len -= t; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 3) != 0) { + panama_short(sc, data, len); + return; + } +#endif + panama_push(sc, data, len >> 5); + rlen = len & 31; + if (rlen > 0) + memcpy(sc->data, + (const unsigned char *)data + len - rlen, rlen); + sc->data_ptr = rlen; +} +#endif + +/* see sph_panama.h */ +void +sph_panama_close(void *cc, void *dst) +{ + sph_panama_context *sc; + unsigned current; + int i; + + sc = cc; + current = sc->data_ptr; + sc->data[current ++] = 0x01; + memset(sc->data + current, 0, (sizeof sc->data) - current); + panama_push(sc, sc->data, 1); + panama_pull(sc, 32); + for (i = 0; i < 8; i ++) + sph_enc32le((unsigned char *)dst + 4 * i, sc->state[i + 9]); + sph_panama_init(sc); +} diff --git a/stratum/sha3/sph_panama.h b/stratum/sha3/sph_panama.h new file mode 100644 index 000000000..763035fb5 --- /dev/null +++ b/stratum/sha3/sph_panama.h @@ -0,0 +1,118 @@ +/* $Id: sph_panama.h 154 2010-04-26 17:00:24Z tp $ */ +/** + * PANAMA interface. + * + * PANAMA has been published in: J. Daemen and C. Clapp, "Fast Hashing + * and Stream Encryption with PANAMA", Fast Software Encryption - + * FSE'98, LNCS 1372, Springer (1998), pp. 60--74. + * + * PANAMA is not fully defined with regards to endianness and related + * topics. This implementation follows strict little-endian conventions: + *
    + *
  • Each 32-byte input block is split into eight 32-bit words, the + * first (leftmost) word being numbered 0.
  • + *
  • Each such 32-bit word is decoded from memory in little-endian + * convention.
  • + *
  • The additional padding bit equal to "1" is added by considering + * the least significant bit in a byte to come first; practically, this + * means that a single byte of value 0x01 is appended to the (byte-oriented) + * message, and then 0 to 31 bytes of value 0x00.
  • + *
  • The output consists of eight 32-bit words; the word numbered 0 is + * written first (in leftmost position) and it is encoded in little-endian + * convention. + *
+ * With these conventions, PANAMA is sometimes known as "PANAMA-LE". The + * PANAMA reference implementation uses our conventions for input, but + * prescribes no convention for output. + * + * ==========================(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_panama.h + * @author Thomas Pornin + */ + +#ifndef SPH_PANAMA_H__ +#define SPH_PANAMA_H__ + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for PANAMA. + */ +#define SPH_SIZE_panama 256 + +/** + * This structure is a context for PANAMA computations: it contains the + * intermediate values and some data from the last entered block. Once + * a PANAMA computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running PANAMA computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char data[32]; /* first field, for alignment */ + unsigned data_ptr; + + sph_u32 buffer[32][8]; + unsigned buffer_ptr; + + sph_u32 state[17]; +#endif +} sph_panama_context; + +/** + * Initialize a PANAMA context. This process performs no memory allocation. + * + * @param cc the PANAMA context (pointer to a sph_panama_context) + */ +void sph_panama_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the PANAMA context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_panama(void *cc, const void *data, size_t len); + +/** + * Terminate the current PANAMA computation and output the result into the + * provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the PANAMA context + * @param dst the destination buffer + */ +void sph_panama_close(void *cc, void *dst); + +#endif diff --git a/stratum/sha3/sph_radiogatun.c b/stratum/sha3/sph_radiogatun.c new file mode 100644 index 000000000..708f45c07 --- /dev/null +++ b/stratum/sha3/sph_radiogatun.c @@ -0,0 +1,1003 @@ +/* $Id: radiogatun.c 226 2010-06-16 17:28:08Z tp $ */ +/* + * RadioGatun implementation. + * + * ==========================(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)============================= + * + * @author Thomas Pornin + */ + +#include +#include + +#include "sph_radiogatun.h" + +#if SPH_SMALL_FOOTPRINT && !defined SPH_SMALL_FOOTPRINT_RADIOGATUN +#define SPH_SMALL_FOOTPRINT_RADIOGATUN 1 +#endif + +/* ======================================================================= */ +/* + * The core macros. We want to unroll 13 successive rounds so that the + * belt rotation becomes pure routing, solved at compilation time, with + * no unnecessary copying. We also wish all state variables to be + * independant local variables, so that the C compiler becomes free to + * map these on registers at it sees fit. This requires some heavy + * preprocessor trickeries, including a full addition macro modulo 13. + * + * These macros are size-independent. Some macros must be defined before + * use: + * WT evaluates to the type for a word (32-bit or 64-bit) + * T truncates a value to the proper word size + * ROR(x, n) right rotation of a word x, with explicit modular + * reduction of the rotation count n by the word size + * INW(i, j) input word j (0, 1, or 2) of block i (0 to 12) + * + * For INW, the input buffer is pointed to by "buf" which has type + * "const unsigned char *". + */ + +#define MUL19(action) do { \ + action(0); \ + action(1); \ + action(2); \ + action(3); \ + action(4); \ + action(5); \ + action(6); \ + action(7); \ + action(8); \ + action(9); \ + action(10); \ + action(11); \ + action(12); \ + action(13); \ + action(14); \ + action(15); \ + action(16); \ + action(17); \ + action(18); \ + } while (0) + +#define DECL19(b) b ## 0, b ## 1, b ## 2, b ## 3, b ## 4, b ## 5, \ + b ## 6, b ## 7, b ## 8, b ## 9, b ## 10, b ## 11, \ + b ## 12, b ## 13, b ## 14, b ## 15, b ## 16, \ + b ## 17, b ## 18 + +#define M19_T7(i) M19_T7_(i) +#define M19_T7_(i) M19_T7_ ## i +#define M19_T7_0 0 +#define M19_T7_1 7 +#define M19_T7_2 14 +#define M19_T7_3 2 +#define M19_T7_4 9 +#define M19_T7_5 16 +#define M19_T7_6 4 +#define M19_T7_7 11 +#define M19_T7_8 18 +#define M19_T7_9 6 +#define M19_T7_10 13 +#define M19_T7_11 1 +#define M19_T7_12 8 +#define M19_T7_13 15 +#define M19_T7_14 3 +#define M19_T7_15 10 +#define M19_T7_16 17 +#define M19_T7_17 5 +#define M19_T7_18 12 + +#define M19_A1(i) M19_A1_(i) +#define M19_A1_(i) M19_A1_ ## i +#define M19_A1_0 1 +#define M19_A1_1 2 +#define M19_A1_2 3 +#define M19_A1_3 4 +#define M19_A1_4 5 +#define M19_A1_5 6 +#define M19_A1_6 7 +#define M19_A1_7 8 +#define M19_A1_8 9 +#define M19_A1_9 10 +#define M19_A1_10 11 +#define M19_A1_11 12 +#define M19_A1_12 13 +#define M19_A1_13 14 +#define M19_A1_14 15 +#define M19_A1_15 16 +#define M19_A1_16 17 +#define M19_A1_17 18 +#define M19_A1_18 0 + +#define M19_A2(i) M19_A2_(i) +#define M19_A2_(i) M19_A2_ ## i +#define M19_A2_0 2 +#define M19_A2_1 3 +#define M19_A2_2 4 +#define M19_A2_3 5 +#define M19_A2_4 6 +#define M19_A2_5 7 +#define M19_A2_6 8 +#define M19_A2_7 9 +#define M19_A2_8 10 +#define M19_A2_9 11 +#define M19_A2_10 12 +#define M19_A2_11 13 +#define M19_A2_12 14 +#define M19_A2_13 15 +#define M19_A2_14 16 +#define M19_A2_15 17 +#define M19_A2_16 18 +#define M19_A2_17 0 +#define M19_A2_18 1 + +#define M19_A4(i) M19_A4_(i) +#define M19_A4_(i) M19_A4_ ## i +#define M19_A4_0 4 +#define M19_A4_1 5 +#define M19_A4_2 6 +#define M19_A4_3 7 +#define M19_A4_4 8 +#define M19_A4_5 9 +#define M19_A4_6 10 +#define M19_A4_7 11 +#define M19_A4_8 12 +#define M19_A4_9 13 +#define M19_A4_10 14 +#define M19_A4_11 15 +#define M19_A4_12 16 +#define M19_A4_13 17 +#define M19_A4_14 18 +#define M19_A4_15 0 +#define M19_A4_16 1 +#define M19_A4_17 2 +#define M19_A4_18 3 + +#define ACC_a(i) ACC_a_(i) +#define ACC_a_(i) a ## i +#define ACC_atmp(i) ACC_atmp_(i) +#define ACC_atmp_(i) atmp ## i + +#define MILL1(i) (atmp ## i = a ## i ^ T(ACC_a(M19_A1(i)) \ + | ~ACC_a(M19_A2(i)))) +#define MILL2(i) (a ## i = ROR(ACC_atmp(M19_T7(i)), ((i * (i + 1)) >> 1))) +#define MILL3(i) (atmp ## i = a ## i ^ ACC_a(M19_A1(i)) ^ ACC_a(M19_A4(i))) +#define MILL4(i) (a ## i = atmp ## i ^ (i == 0)) + +#define MILL do { \ + WT DECL19(atmp); \ + MUL19(MILL1); \ + MUL19(MILL2); \ + MUL19(MILL3); \ + MUL19(MILL4); \ + } while (0) + +#define DECL13(b) b ## 0 ## _0, b ## 0 ## _1, b ## 0 ## _2, \ + b ## 1 ## _0, b ## 1 ## _1, b ## 1 ## _2, \ + b ## 2 ## _0, b ## 2 ## _1, b ## 2 ## _2, \ + b ## 3 ## _0, b ## 3 ## _1, b ## 3 ## _2, \ + b ## 4 ## _0, b ## 4 ## _1, b ## 4 ## _2, \ + b ## 5 ## _0, b ## 5 ## _1, b ## 5 ## _2, \ + b ## 6 ## _0, b ## 6 ## _1, b ## 6 ## _2, \ + b ## 7 ## _0, b ## 7 ## _1, b ## 7 ## _2, \ + b ## 8 ## _0, b ## 8 ## _1, b ## 8 ## _2, \ + b ## 9 ## _0, b ## 9 ## _1, b ## 9 ## _2, \ + b ## 10 ## _0, b ## 10 ## _1, b ## 10 ## _2, \ + b ## 11 ## _0, b ## 11 ## _1, b ## 11 ## _2, \ + b ## 12 ## _0, b ## 12 ## _1, b ## 12 ## _2 + +#define M13_A(i, j) M13_A_(i, j) +#define M13_A_(i, j) M13_A_ ## i ## _ ## j +#define M13_A_0_0 0 +#define M13_A_0_1 1 +#define M13_A_0_2 2 +#define M13_A_0_3 3 +#define M13_A_0_4 4 +#define M13_A_0_5 5 +#define M13_A_0_6 6 +#define M13_A_0_7 7 +#define M13_A_0_8 8 +#define M13_A_0_9 9 +#define M13_A_0_10 10 +#define M13_A_0_11 11 +#define M13_A_0_12 12 +#define M13_A_1_0 1 +#define M13_A_1_1 2 +#define M13_A_1_2 3 +#define M13_A_1_3 4 +#define M13_A_1_4 5 +#define M13_A_1_5 6 +#define M13_A_1_6 7 +#define M13_A_1_7 8 +#define M13_A_1_8 9 +#define M13_A_1_9 10 +#define M13_A_1_10 11 +#define M13_A_1_11 12 +#define M13_A_1_12 0 +#define M13_A_2_0 2 +#define M13_A_2_1 3 +#define M13_A_2_2 4 +#define M13_A_2_3 5 +#define M13_A_2_4 6 +#define M13_A_2_5 7 +#define M13_A_2_6 8 +#define M13_A_2_7 9 +#define M13_A_2_8 10 +#define M13_A_2_9 11 +#define M13_A_2_10 12 +#define M13_A_2_11 0 +#define M13_A_2_12 1 +#define M13_A_3_0 3 +#define M13_A_3_1 4 +#define M13_A_3_2 5 +#define M13_A_3_3 6 +#define M13_A_3_4 7 +#define M13_A_3_5 8 +#define M13_A_3_6 9 +#define M13_A_3_7 10 +#define M13_A_3_8 11 +#define M13_A_3_9 12 +#define M13_A_3_10 0 +#define M13_A_3_11 1 +#define M13_A_3_12 2 +#define M13_A_4_0 4 +#define M13_A_4_1 5 +#define M13_A_4_2 6 +#define M13_A_4_3 7 +#define M13_A_4_4 8 +#define M13_A_4_5 9 +#define M13_A_4_6 10 +#define M13_A_4_7 11 +#define M13_A_4_8 12 +#define M13_A_4_9 0 +#define M13_A_4_10 1 +#define M13_A_4_11 2 +#define M13_A_4_12 3 +#define M13_A_5_0 5 +#define M13_A_5_1 6 +#define M13_A_5_2 7 +#define M13_A_5_3 8 +#define M13_A_5_4 9 +#define M13_A_5_5 10 +#define M13_A_5_6 11 +#define M13_A_5_7 12 +#define M13_A_5_8 0 +#define M13_A_5_9 1 +#define M13_A_5_10 2 +#define M13_A_5_11 3 +#define M13_A_5_12 4 +#define M13_A_6_0 6 +#define M13_A_6_1 7 +#define M13_A_6_2 8 +#define M13_A_6_3 9 +#define M13_A_6_4 10 +#define M13_A_6_5 11 +#define M13_A_6_6 12 +#define M13_A_6_7 0 +#define M13_A_6_8 1 +#define M13_A_6_9 2 +#define M13_A_6_10 3 +#define M13_A_6_11 4 +#define M13_A_6_12 5 +#define M13_A_7_0 7 +#define M13_A_7_1 8 +#define M13_A_7_2 9 +#define M13_A_7_3 10 +#define M13_A_7_4 11 +#define M13_A_7_5 12 +#define M13_A_7_6 0 +#define M13_A_7_7 1 +#define M13_A_7_8 2 +#define M13_A_7_9 3 +#define M13_A_7_10 4 +#define M13_A_7_11 5 +#define M13_A_7_12 6 +#define M13_A_8_0 8 +#define M13_A_8_1 9 +#define M13_A_8_2 10 +#define M13_A_8_3 11 +#define M13_A_8_4 12 +#define M13_A_8_5 0 +#define M13_A_8_6 1 +#define M13_A_8_7 2 +#define M13_A_8_8 3 +#define M13_A_8_9 4 +#define M13_A_8_10 5 +#define M13_A_8_11 6 +#define M13_A_8_12 7 +#define M13_A_9_0 9 +#define M13_A_9_1 10 +#define M13_A_9_2 11 +#define M13_A_9_3 12 +#define M13_A_9_4 0 +#define M13_A_9_5 1 +#define M13_A_9_6 2 +#define M13_A_9_7 3 +#define M13_A_9_8 4 +#define M13_A_9_9 5 +#define M13_A_9_10 6 +#define M13_A_9_11 7 +#define M13_A_9_12 8 +#define M13_A_10_0 10 +#define M13_A_10_1 11 +#define M13_A_10_2 12 +#define M13_A_10_3 0 +#define M13_A_10_4 1 +#define M13_A_10_5 2 +#define M13_A_10_6 3 +#define M13_A_10_7 4 +#define M13_A_10_8 5 +#define M13_A_10_9 6 +#define M13_A_10_10 7 +#define M13_A_10_11 8 +#define M13_A_10_12 9 +#define M13_A_11_0 11 +#define M13_A_11_1 12 +#define M13_A_11_2 0 +#define M13_A_11_3 1 +#define M13_A_11_4 2 +#define M13_A_11_5 3 +#define M13_A_11_6 4 +#define M13_A_11_7 5 +#define M13_A_11_8 6 +#define M13_A_11_9 7 +#define M13_A_11_10 8 +#define M13_A_11_11 9 +#define M13_A_11_12 10 +#define M13_A_12_0 12 +#define M13_A_12_1 0 +#define M13_A_12_2 1 +#define M13_A_12_3 2 +#define M13_A_12_4 3 +#define M13_A_12_5 4 +#define M13_A_12_6 5 +#define M13_A_12_7 6 +#define M13_A_12_8 7 +#define M13_A_12_9 8 +#define M13_A_12_10 9 +#define M13_A_12_11 10 +#define M13_A_12_12 11 + +#define M13_N(i) M13_N_(i) +#define M13_N_(i) M13_N_ ## i +#define M13_N_0 12 +#define M13_N_1 11 +#define M13_N_2 10 +#define M13_N_3 9 +#define M13_N_4 8 +#define M13_N_5 7 +#define M13_N_6 6 +#define M13_N_7 5 +#define M13_N_8 4 +#define M13_N_9 3 +#define M13_N_10 2 +#define M13_N_11 1 +#define M13_N_12 0 + +#define ACC_b(i, k) ACC_b_(i, k) +#define ACC_b_(i, k) b ## i ## _ ## k + +#define ROUND_ELT(k, s) do { \ + if ((bj += 3) == 39) \ + bj = 0; \ + sc->b[bj + s] ^= a ## k; \ + } while (0) + +#define ROUND_SF(j) do { \ + size_t bj = (j) * 3; \ + ROUND_ELT(1, 0); \ + ROUND_ELT(2, 1); \ + ROUND_ELT(3, 2); \ + ROUND_ELT(4, 0); \ + ROUND_ELT(5, 1); \ + ROUND_ELT(6, 2); \ + ROUND_ELT(7, 0); \ + ROUND_ELT(8, 1); \ + ROUND_ELT(9, 2); \ + ROUND_ELT(10, 0); \ + ROUND_ELT(11, 1); \ + ROUND_ELT(12, 2); \ + MILL; \ + bj = (j) * 3; \ + a ## 13 ^= sc->b[bj + 0]; \ + a ## 14 ^= sc->b[bj + 1]; \ + a ## 15 ^= sc->b[bj + 2]; \ + } while (0) + +#define INPUT_SF(j, p0, p1, p2) do { \ + size_t bj = ((j) + 1) * 3; \ + if (bj == 39) \ + bj = 0; \ + sc->b[bj + 0] ^= (p0); \ + sc->b[bj + 1] ^= (p1); \ + sc->b[bj + 2] ^= (p2); \ + a16 ^= (p0); \ + a17 ^= (p1); \ + a18 ^= (p2); \ + } while (0) + + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN + +#define ROUND ROUND_SF +#define INPUT INPUT_SF + +#else + +/* + * Round function R, on base j. The value j is such that B[0] is actually + * b[j] after the initial rotation. On the 13-round macro, j has the + * successive values 12, 11, 10... 1, 0. + */ +#define ROUND(j) do { \ + ACC_b(M13_A(1, j), 0) ^= a ## 1; \ + ACC_b(M13_A(2, j), 1) ^= a ## 2; \ + ACC_b(M13_A(3, j), 2) ^= a ## 3; \ + ACC_b(M13_A(4, j), 0) ^= a ## 4; \ + ACC_b(M13_A(5, j), 1) ^= a ## 5; \ + ACC_b(M13_A(6, j), 2) ^= a ## 6; \ + ACC_b(M13_A(7, j), 0) ^= a ## 7; \ + ACC_b(M13_A(8, j), 1) ^= a ## 8; \ + ACC_b(M13_A(9, j), 2) ^= a ## 9; \ + ACC_b(M13_A(10, j), 0) ^= a ## 10; \ + ACC_b(M13_A(11, j), 1) ^= a ## 11; \ + ACC_b(M13_A(12, j), 2) ^= a ## 12; \ + MILL; \ + a ## 13 ^= ACC_b(j, 0); \ + a ## 14 ^= ACC_b(j, 1); \ + a ## 15 ^= ACC_b(j, 2); \ + } while (0) + +#define INPUT(j, p0, p1, p2) do { \ + ACC_b(M13_A(1, j), 0) ^= (p0); \ + ACC_b(M13_A(1, j), 1) ^= (p1); \ + ACC_b(M13_A(1, j), 2) ^= (p2); \ + a16 ^= (p0); \ + a17 ^= (p1); \ + a18 ^= (p2); \ + } while (0) + +#endif + +#define MUL13(action) do { \ + action(0); \ + action(1); \ + action(2); \ + action(3); \ + action(4); \ + action(5); \ + action(6); \ + action(7); \ + action(8); \ + action(9); \ + action(10); \ + action(11); \ + action(12); \ + } while (0) + +#define MILL_READ_ELT(i) do { \ + a ## i = sc->a[i]; \ + } while (0) + +#define MILL_WRITE_ELT(i) do { \ + sc->a[i] = a ## i; \ + } while (0) + +#define STATE_READ_SF do { \ + MUL19(MILL_READ_ELT); \ + } while (0) + +#define STATE_WRITE_SF do { \ + MUL19(MILL_WRITE_ELT); \ + } while (0) + +#define PUSH13_SF do { \ + WT DECL19(a); \ + const unsigned char *buf; \ + \ + buf = data; \ + STATE_READ_SF; \ + while (len >= sizeof sc->data) { \ + size_t mk; \ + for (mk = 13; mk > 0; mk --) { \ + WT p0 = INW(0, 0); \ + WT p1 = INW(0, 1); \ + WT p2 = INW(0, 2); \ + INPUT_SF(mk - 1, p0, p1, p2); \ + ROUND_SF(mk - 1); \ + buf += (sizeof sc->data) / 13; \ + len -= (sizeof sc->data) / 13; \ + } \ + } \ + STATE_WRITE_SF; \ + return len; \ + } while (0) + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN + +#define STATE_READ STATE_READ_SF +#define STATE_WRITE STATE_WRITE_SF +#define PUSH13 PUSH13_SF + +#else + +#define BELT_READ_ELT(i) do { \ + b ## i ## _0 = sc->b[3 * i + 0]; \ + b ## i ## _1 = sc->b[3 * i + 1]; \ + b ## i ## _2 = sc->b[3 * i + 2]; \ + } while (0) + +#define BELT_WRITE_ELT(i) do { \ + sc->b[3 * i + 0] = b ## i ## _0; \ + sc->b[3 * i + 1] = b ## i ## _1; \ + sc->b[3 * i + 2] = b ## i ## _2; \ + } while (0) + +#define STATE_READ do { \ + MUL13(BELT_READ_ELT); \ + MUL19(MILL_READ_ELT); \ + } while (0) + +#define STATE_WRITE do { \ + MUL13(BELT_WRITE_ELT); \ + MUL19(MILL_WRITE_ELT); \ + } while (0) + +/* + * Input data by chunks of 13*3 blocks. This is the body of the + * radiogatun32_push13() and radiogatun64_push13() functions. + */ +#define PUSH13 do { \ + WT DECL19(a), DECL13(b); \ + const unsigned char *buf; \ + \ + buf = data; \ + STATE_READ; \ + while (len >= sizeof sc->data) { \ + WT p0, p1, p2; \ + MUL13(PUSH13_ELT); \ + buf += sizeof sc->data; \ + len -= sizeof sc->data; \ + } \ + STATE_WRITE; \ + return len; \ + } while (0) + +#define PUSH13_ELT(k) do { \ + p0 = INW(k, 0); \ + p1 = INW(k, 1); \ + p2 = INW(k, 2); \ + INPUT(M13_N(k), p0, p1, p2); \ + ROUND(M13_N(k)); \ + } while (0) + +#endif + +#define BLANK13_SF do { \ + size_t mk = 13; \ + while (mk -- > 0) \ + ROUND_SF(mk); \ + } while (0) + +#define BLANK1_SF do { \ + WT tmp0, tmp1, tmp2; \ + ROUND_SF(12); \ + tmp0 = sc->b[36]; \ + tmp1 = sc->b[37]; \ + tmp2 = sc->b[38]; \ + memmove(sc->b + 3, sc->b, 36 * sizeof sc->b[0]); \ + sc->b[0] = tmp0; \ + sc->b[1] = tmp1; \ + sc->b[2] = tmp2; \ + } while (0) + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN + +#define BLANK13 BLANK13_SF +#define BLANK1 BLANK1_SF + +#else + +/* + * Run 13 blank rounds. This macro expects the "a" and "b" state variables + * to be alread declared. + */ +#define BLANK13 MUL13(BLANK13_ELT) + +#define BLANK13_ELT(k) ROUND(M13_N(k)) + +#define MUL12(action) do { \ + action(0); \ + action(1); \ + action(2); \ + action(3); \ + action(4); \ + action(5); \ + action(6); \ + action(7); \ + action(8); \ + action(9); \ + action(10); \ + action(11); \ + } while (0) + +/* + * Run a single blank round, and physically rotate the belt. This is used + * for the last blank rounds, and the output rounds. This macro expects the + * "a" abd "b" state variables to be already declared. + */ +#define BLANK1 do { \ + WT tmp0, tmp1, tmp2; \ + ROUND(12); \ + tmp0 = b0_0; \ + tmp1 = b0_1; \ + tmp2 = b0_2; \ + MUL12(BLANK1_ELT); \ + b1_0 = tmp0; \ + b1_1 = tmp1; \ + b1_2 = tmp2; \ + } while (0) + +#define BLANK1_ELT(i) do { \ + ACC_b(M13_A(M13_N(i), 1), 0) = ACC_b(M13_N(i), 0); \ + ACC_b(M13_A(M13_N(i), 1), 1) = ACC_b(M13_N(i), 1); \ + ACC_b(M13_A(M13_N(i), 1), 2) = ACC_b(M13_N(i), 2); \ + } while (0) + +#endif + +#define NO_TOKEN + +/* + * Perform padding, then blank rounds, then output some words. This is + * the body of sph_radiogatun32_close() and sph_radiogatun64_close(). + */ +#define CLOSE_SF(width) CLOSE_GEN(width, \ + NO_TOKEN, STATE_READ_SF, BLANK1_SF, BLANK13_SF) + +#if SPH_SMALL_FOOTPRINT_RADIOGATUN +#define CLOSE CLOSE_SF +#else +#define CLOSE(width) CLOSE_GEN(width, \ + WT DECL13(b);, STATE_READ, BLANK1, BLANK13) +#endif + +#define CLOSE_GEN(width, WTb13, state_read, blank1, blank13) do { \ + unsigned ptr, num; \ + unsigned char *out; \ + WT DECL19(a); \ + WTb13 \ + \ + ptr = sc->data_ptr; \ + sc->data[ptr ++] = 0x01; \ + memset(sc->data + ptr, 0, (sizeof sc->data) - ptr); \ + radiogatun ## width ## _push13(sc, sc->data, sizeof sc->data); \ + \ + num = 17; \ + for (;;) { \ + ptr += 3 * (width >> 3); \ + if (ptr > sizeof sc->data) \ + break; \ + num --; \ + } \ + \ + state_read; \ + if (num >= 13) { \ + blank13; \ + num -= 13; \ + } \ + while (num -- > 0) \ + blank1; \ + \ + num = 0; \ + out = dst; \ + for (;;) { \ + OUTW(out, a1); \ + out += width >> 3; \ + OUTW(out, a2); \ + out += width >> 3; \ + num += 2 * (width >> 3); \ + if (num >= 32) \ + break; \ + blank1; \ + } \ + INIT; \ + } while (0) + +/* + * Initialize context structure. + */ +#if SPH_LITTLE_ENDIAN || SPH_BIG_ENDIAN + +#define INIT do { \ + memset(sc->a, 0, sizeof sc->a); \ + memset(sc->b, 0, sizeof sc->b); \ + sc->data_ptr = 0; \ + } while (0) + +#else + +#define INIT do { \ + size_t u; \ + for (u = 0; u < 19; u ++) \ + sc->a[u] = 0; \ + for (u = 0; u < 39; u ++) \ + sc->b[u] = 0; \ + sc->data_ptr = 0; \ + } while (0) + +#endif + +/* ======================================================================= */ +/* + * RadioGatun[32]. + */ + +#if !SPH_NO_RG32 + +#undef WT +#define WT sph_u32 +#undef T +#define T SPH_T32 +#undef ROR +#define ROR(x, n) SPH_T32(((x) << ((32 - (n)) & 31)) | ((x) >> ((n) & 31))) +#undef INW +#define INW(i, j) sph_dec32le_aligned(buf + (4 * (3 * (i) + (j)))) +#undef OUTW +#define OUTW(b, v) sph_enc32le(b, v) + +/* + * Insert data by big chunks of 13*12 = 156 bytes. Returned value is the + * number of remaining bytes (between 0 and 155). This method assumes that + * the input data is suitably aligned. + */ +static size_t +radiogatun32_push13(sph_radiogatun32_context *sc, const void *data, size_t len) +{ + PUSH13; +} + +/* see sph_radiogatun.h */ +void +sph_radiogatun32_init(void *cc) +{ + sph_radiogatun32_context *sc; + + sc = cc; + INIT; +} + +#ifdef SPH_UPTR +static void +radiogatun32_short(void *cc, const void *data, size_t len) +#else +/* see sph_radiogatun.h */ +void +sph_radiogatun32(void *cc, const void *data, size_t len) +#endif +{ + sph_radiogatun32_context *sc; + unsigned ptr; + + sc = cc; + ptr = sc->data_ptr; + while (len > 0) { + size_t clen; + + clen = (sizeof sc->data) - ptr; + if (clen > len) + clen = len; + memcpy(sc->data + ptr, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + ptr += clen; + if (ptr == sizeof sc->data) { + radiogatun32_push13(sc, sc->data, sizeof sc->data); + ptr = 0; + } + } + sc->data_ptr = ptr; +} + +#ifdef SPH_UPTR +/* see sph_radiogatun.h */ +void +sph_radiogatun32(void *cc, const void *data, size_t len) +{ + sph_radiogatun32_context *sc; + unsigned ptr; + size_t rlen; + + if (len < (2 * sizeof sc->data)) { + radiogatun32_short(cc, data, len); + return; + } + sc = cc; + ptr = sc->data_ptr; + if (ptr > 0) { + unsigned t; + + t = (sizeof sc->data) - ptr; + radiogatun32_short(sc, data, t); + data = (const unsigned char *)data + t; + len -= t; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 3) != 0) { + radiogatun32_short(sc, data, len); + return; + } +#endif + rlen = radiogatun32_push13(sc, data, len); + memcpy(sc->data, (const unsigned char *)data + len - rlen, rlen); + sc->data_ptr = rlen; +} +#endif + +/* see sph_radiogatun.h */ +void +sph_radiogatun32_close(void *cc, void *dst) +{ + sph_radiogatun32_context *sc; + + sc = cc; + CLOSE(32); +} + +#endif + +/* ======================================================================= */ +/* + * RadioGatun[64]. Compiled only if a 64-bit or more type is available. + */ + +#if SPH_64 + +#if !SPH_NO_RG64 + +#undef WT +#define WT sph_u64 +#undef T +#define T SPH_T64 +#undef ROR +#define ROR(x, n) SPH_T64(((x) << ((64 - (n)) & 63)) | ((x) >> ((n) & 63))) +#undef INW +#define INW(i, j) sph_dec64le_aligned(buf + (8 * (3 * (i) + (j)))) +#undef OUTW +#define OUTW(b, v) sph_enc64le(b, v) + +/* + * On 32-bit x86, register pressure is such that using the small + * footprint version is a net gain (x2 speed), because that variant + * uses fewer local variables. + */ +#if SPH_I386_MSVC || SPH_I386_GCC || defined __i386__ +#undef PUSH13 +#define PUSH13 PUSH13_SF +#undef CLOSE +#define CLOSE CLOSE_SF +#endif + +/* + * Insert data by big chunks of 13*24 = 312 bytes. Returned value is the + * number of remaining bytes (between 0 and 311). This method assumes that + * the input data is suitably aligned. + */ +static size_t +radiogatun64_push13(sph_radiogatun64_context *sc, const void *data, size_t len) +{ + PUSH13; +} + +/* see sph_radiogatun.h */ +void +sph_radiogatun64_init(void *cc) +{ + sph_radiogatun64_context *sc; + + sc = cc; + INIT; +} + +#ifdef SPH_UPTR +static void +radiogatun64_short(void *cc, const void *data, size_t len) +#else +/* see sph_radiogatun.h */ +void +sph_radiogatun64(void *cc, const void *data, size_t len) +#endif +{ + sph_radiogatun64_context *sc; + unsigned ptr; + + sc = cc; + ptr = sc->data_ptr; + while (len > 0) { + size_t clen; + + clen = (sizeof sc->data) - ptr; + if (clen > len) + clen = len; + memcpy(sc->data + ptr, data, clen); + data = (const unsigned char *)data + clen; + len -= clen; + ptr += clen; + if (ptr == sizeof sc->data) { + radiogatun64_push13(sc, sc->data, sizeof sc->data); + ptr = 0; + } + } + sc->data_ptr = ptr; +} + +#ifdef SPH_UPTR +/* see sph_radiogatun.h */ +void +sph_radiogatun64(void *cc, const void *data, size_t len) +{ + sph_radiogatun64_context *sc; + unsigned ptr; + size_t rlen; + + if (len < (2 * sizeof sc->data)) { + radiogatun64_short(cc, data, len); + return; + } + sc = cc; + ptr = sc->data_ptr; + if (ptr > 0) { + unsigned t; + + t = (sizeof sc->data) - ptr; + radiogatun64_short(sc, data, t); + data = (const unsigned char *)data + t; + len -= t; + } +#if !SPH_UNALIGNED + if (((SPH_UPTR)data & 7) != 0) { + radiogatun64_short(sc, data, len); + return; + } +#endif + rlen = radiogatun64_push13(sc, data, len); + memcpy(sc->data, (const unsigned char *)data + len - rlen, rlen); + sc->data_ptr = rlen; +} +#endif + +/* see sph_radiogatun.h */ +void +sph_radiogatun64_close(void *cc, void *dst) +{ + sph_radiogatun64_context *sc; + + sc = cc; + CLOSE(64); +} + +#endif + +#endif diff --git a/stratum/sha3/sph_radiogatun.h b/stratum/sha3/sph_radiogatun.h new file mode 100644 index 000000000..f8cedc233 --- /dev/null +++ b/stratum/sha3/sph_radiogatun.h @@ -0,0 +1,186 @@ +/* $Id: sph_radiogatun.h 226 2010-06-16 17:28:08Z tp $ */ +/** + * RadioGatun interface. + * + * RadioGatun has been published in: G. Bertoni, J. Daemen, M. Peeters + * and G. Van Assche, "RadioGatun, a belt-and-mill hash function", + * presented at the Second Cryptographic Hash Workshop, Santa Barbara, + * August 24-25, 2006. The main Web site, containing that article, the + * reference code and some test vectors, appears to be currently located + * at the following URL: http://radiogatun.noekeon.org/ + * + * The presentation article does not specify endianness or padding. The + * reference code uses the following conventions, which we also apply + * here: + *
    + *
  • The input message is an integral number of sequences of three + * words. Each word is either a 32-bit of 64-bit word (depending on + * the version of RadioGatun).
  • + *
  • Input bytes are decoded into words using little-endian + * convention.
  • + *
  • Padding consists of a single bit of value 1, using little-endian + * convention within bytes (i.e. for a byte-oriented input, a single + * byte of value 0x01 is appended), then enough bits of value 0 to finish + * the current block.
  • + *
  • Output consists of 256 bits. Successive output words are encoded + * with little-endian convention.
  • + *
+ * These conventions are very close to those we use for PANAMA, which is + * a close ancestor or RadioGatun. + * + * RadioGatun is actually a family of functions, depending on some + * internal parameters. We implement here two functions, with a "belt + * length" of 13, a "belt width" of 3, and a "mill length" of 19. The + * RadioGatun[32] version uses 32-bit words, while the RadioGatun[64] + * variant uses 64-bit words. + * + * Strictly speaking, the name "RadioGatun" should use an acute accent + * on the "u", which we omitted here to keep strict ASCII-compatibility + * of this file. + * + * ==========================(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_radiogatun.h + * @author Thomas Pornin + */ + +#ifndef SPH_RADIOGATUN_H__ +#define SPH_RADIOGATUN_H__ + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for RadioGatun[32]. + */ +#define SPH_SIZE_radiogatun32 256 + +/** + * This structure is a context for RadioGatun[32] computations: it + * contains intermediate values and some data from the last entered + * block. Once a RadioGatun[32] computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running RadioGatun[32] + * computation can be cloned by copying the context (e.g. with a + * simple memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char data[156]; /* first field, for alignment */ + unsigned data_ptr; + sph_u32 a[19], b[39]; +#endif +} sph_radiogatun32_context; + +/** + * Initialize a RadioGatun[32] context. This process performs no + * memory allocation. + * + * @param cc the RadioGatun[32] context (pointer to a + * sph_radiogatun32_context) + */ +void sph_radiogatun32_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the RadioGatun[32] context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_radiogatun32(void *cc, const void *data, size_t len); + +/** + * Terminate the current RadioGatun[32] computation and output the + * result into the provided buffer. The destination buffer must be wide + * enough to accomodate the result (32 bytes). The context is + * automatically reinitialized. + * + * @param cc the RadioGatun[32] context + * @param dst the destination buffer + */ +void sph_radiogatun32_close(void *cc, void *dst); + +#if SPH_64 + +/** + * Output size (in bits) for RadioGatun[64]. + */ +#define SPH_SIZE_radiogatun64 256 + +/** + * This structure is a context for RadioGatun[64] computations: it + * contains intermediate values and some data from the last entered + * block. Once a RadioGatun[64] computation has been performed, the + * context can be reused for another computation. + * + * The contents of this structure are private. A running RadioGatun[64] + * computation can be cloned by copying the context (e.g. with a + * simple memcpy()). + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char data[312]; /* first field, for alignment */ + unsigned data_ptr; + sph_u64 a[19], b[39]; +#endif +} sph_radiogatun64_context; + +/** + * Initialize a RadioGatun[64] context. This process performs no + * memory allocation. + * + * @param cc the RadioGatun[64] context (pointer to a + * sph_radiogatun64_context) + */ +void sph_radiogatun64_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the RadioGatun[64] context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_radiogatun64(void *cc, const void *data, size_t len); + +/** + * Terminate the current RadioGatun[64] computation and output the + * result into the provided buffer. The destination buffer must be wide + * enough to accomodate the result (32 bytes). The context is + * automatically reinitialized. + * + * @param cc the RadioGatun[64] context + * @param dst the destination buffer + */ +void sph_radiogatun64_close(void *cc, void *dst); + +#endif + +#endif \ No newline at end of file diff --git a/stratum/sha3/sph_streebog.h b/stratum/sha3/sph_streebog.h new file mode 100644 index 000000000..a70b0859c --- /dev/null +++ b/stratum/sha3/sph_streebog.h @@ -0,0 +1,185 @@ +/* $Id: sph_gost.h 216 2010-06-08 09:46:57Z tp $ */ +/** + * GOST interface. This is the interface for GOST R 12 with the + * recommended parameters for SHA-3, with output lengths 256 + * and 512 bits. + * + * ==========================(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_gost.h + * @author Mish + */ + +#ifndef SPH_GOST_H__ +#define SPH_GOST_H__ + +#ifdef __cplusplus +extern "C"{ +#endif + +#include +#include "sph_types.h" + +/** + * Output size (in bits) for GOST-256. + */ +#define SPH_SIZE_gost256 256 + +/** + * Output size (in bits) for GOST-512. + */ +#define SPH_SIZE_gost512 512 + +/** + * This structure is a context for Keccak computations: it contains the + * intermediate values and some data from the last entered block. Once a + * GOST computation has been performed, the context can be reused for + * another computation. + * + * The contents of this structure are private. A running GOST computation + * can be cloned by copying the context (e.g. with a simple + * memcpy()). + */ + +/** + * This structure is a context for Gost-256 computations. + */ + +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[32]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[3][8]; +#endif +} sph_gost256_context; + +/** + * This structure is a context for Gost-512 computations. + */ +typedef struct { +#ifndef DOXYGEN_IGNORE + unsigned char buf[64]; /* first field, for alignment */ + size_t ptr; + sph_u32 V[5][8]; +#endif +} sph_gost512_context; + + +/** + * Initialize a GOST-256 context. This process performs no memory allocation. + * + * @param cc the GOST-256 context (pointer to a + * sph_gost256_context) + */ +void sph_gost256_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the Gost-256 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_gost256(void *cc, const void *data, size_t len); + +/** + * Terminate the current GOST-256 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (32 bytes). The context is automatically + * reinitialized. + * + * @param cc the GOST-256 context + * @param dst the destination buffer + */ +void sph_gost256_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (32 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the GOST-256 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_gost256_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +/** + * Initialize a Gost-512 context. This process performs no memory allocation. + * + * @param cc the GOST-512 context (pointer to a + * sph_gost512_context) + */ +void sph_gost512_init(void *cc); + +/** + * Process some data bytes. It is acceptable that len is zero + * (in which case this function does nothing). + * + * @param cc the GOST-512 context + * @param data the input data + * @param len the input data length (in bytes) + */ +void sph_gost512(void *cc, const void *data, size_t len); + +/** + * Terminate the current GOST-512 computation and output the result into + * the provided buffer. The destination buffer must be wide enough to + * accomodate the result (64 bytes). The context is automatically + * reinitialized. + * + * @param cc the GOST-512 context + * @param dst the destination buffer + */ +void sph_gost512_close(void *cc, void *dst); + +/** + * Add a few additional bits (0 to 7) to the current computation, then + * terminate it and output the result in the provided buffer, which must + * be wide enough to accomodate the result (64 bytes). If bit number i + * in ub has value 2^i, then the extra bits are those + * numbered 7 downto 8-n (this is the big-endian convention at the byte + * level). The context is automatically reinitialized. + * + * @param cc the GOST-512 context + * @param ub the extra bits + * @param n the number of extra bits (0 to 7) + * @param dst the destination buffer + */ +void sph_gost512_addbits_and_close( + void *cc, unsigned ub, unsigned n, void *dst); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/stratum/sha3/streebog.c b/stratum/sha3/streebog.c new file mode 100644 index 000000000..7107643c3 --- /dev/null +++ b/stratum/sha3/streebog.c @@ -0,0 +1,1045 @@ +/* Streebog GOST hash function for sib algo SibCoin */ + +#include +#include +#include +#include + +#include "sph_streebog.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +#ifdef _MSC_VER +#pragma warning (disable: 4146) +#endif + +//-------------------------------------------------------------------------------------------- +// +// Streebog 512 implementation +// +//-------------------------------------------------------------------------------------------- + + +// Tables for function F +static const sph_u64 TG[8][256] = {{ + 0xE6F87E5C5B711FD0,0x258377800924FA16,0xC849E07E852EA4A8,0x5B4686A18F06C16A, + 0x0B32E9A2D77B416E,0xABDA37A467815C66,0xF61796A81A686676,0xF5DC0B706391954B, + 0x4862F38DB7E64BF1,0xFF5C629A68BD85C5,0xCB827DA6FCD75795,0x66D36DAF69B9F089, + 0x356C9F74483D83B0,0x7CBCECB1238C99A1,0x36A702AC31C4708D,0x9EB6A8D02FBCDFD6, + 0x8B19FA51E5B3AE37,0x9CCFB5408A127D0B,0xBC0C78B508208F5A,0xE533E3842288ECED, + 0xCEC2C7D377C15FD2,0xEC7817B6505D0F5E,0xB94CC2C08336871D,0x8C205DB4CB0B04AD, + 0x763C855B28A0892F,0x588D1B79F6FF3257,0x3FECF69E4311933E,0x0FC0D39F803A18C9, + 0xEE010A26F5F3AD83,0x10EFE8F4411979A6,0x5DCDA10C7DE93A10,0x4A1BEE1D1248E92C, + 0x53BFF2DB21847339,0xB4F50CCFA6A23D09,0x5FB4BC9CD84798CD,0xE88A2D8B071C56F9, + 0x7F7771695A756A9C,0xC5F02E71A0BA1EBC,0xA663F9AB4215E672,0x2EB19E22DE5FBB78, + 0x0DB9CE0F2594BA14,0x82520E6397664D84,0x2F031E6A0208EA98,0x5C7F2144A1BE6BF0, + 0x7A37CB1CD16362DB,0x83E08E2B4B311C64,0xCF70479BAB960E32,0x856BA986B9DEE71E, + 0xB5478C877AF56CE9,0xB8FE42885F61D6FD,0x1BDD0156966238C8,0x622157923EF8A92E, + 0xFC97FF42114476F8,0x9D7D350856452CEB,0x4C90C9B0E0A71256,0x2308502DFBCB016C, + 0x2D7A03FAA7A64845,0xF46E8B38BFC6C4AB,0xBDBEF8FDD477DEBA,0x3AAC4CEBC8079B79, + 0xF09CB105E8879D0C,0x27FA6A10AC8A58CB,0x8960E7C1401D0CEA,0x1A6F811E4A356928, + 0x90C4FB0773D196FF,0x43501A2F609D0A9F,0xF7A516E0C63F3796,0x1CE4A6B3B8DA9252, + 0x1324752C38E08A9B,0xA5A864733BEC154F,0x2BF124575549B33F,0xD766DB15440DC5C7, + 0xA7D179E39E42B792,0xDADF151A61997FD3,0x86A0345EC0271423,0x38D5517B6DA939A4, + 0x6518F077104003B4,0x02791D90A5AEA2DD,0x88D267899C4A5D0A,0x930F66DF0A2865C2, + 0x4EE9D4204509B08B,0x325538916685292A,0x412907BFC533A842,0xB27E2B62544DC673, + 0x6C5304456295E007,0x5AF406E95351908A,0x1F2F3B6BC123616F,0xC37B09DC5255E5C6, + 0x3967D133B1FE6844,0x298839C7F0E711E2,0x409B87F71964F9A2,0xE938ADC3DB4B0719, + 0x0C0B4E47F9C3EBF4,0x5534D576D36B8843,0x4610A05AEB8B02D8,0x20C3CDF58232F251, + 0x6DE1840DBEC2B1E7,0xA0E8DE06B0FA1D08,0x7B854B540D34333B,0x42E29A67BCCA5B7F, + 0xD8A6088AC437DD0E,0xC63BB3A9D943ED81,0x21714DBD5E65A3B1,0x6761EDE7B5EEA169, + 0x2431F7C8D573ABF6,0xD51FC685E1A3671A,0x5E063CD40410C92D,0x283AB98F2CB04002, + 0x8FEBC06CB2F2F790,0x17D64F116FA1D33C,0xE07359F1A99EE4AA,0x784ED68C74CDC006, + 0x6E2A19D5C73B42DA,0x8712B4161C7045C3,0x371582E4ED93216D,0xACE390414939F6FC, + 0x7EC5F12186223B7C,0xC0B094042BAC16FB,0xF9D745379A527EBF,0x737C3F2EA3B68168, + 0x33E7B8D9BAD278CA,0xA9A32A34C22FFEBB,0xE48163CCFEDFBD0D,0x8E5940246EA5A670, + 0x51C6EF4B842AD1E4,0x22BAD065279C508C,0xD91488C218608CEE,0x319EA5491F7CDA17, + 0xD394E128134C9C60,0x094BF43272D5E3B3,0x9BF612A5A4AAD791,0xCCBBDA43D26FFD0F, + 0x34DE1F3C946AD250,0x4F5B5468995EE16B,0xDF9FAF6FEA8F7794,0x2648EA5870DD092B, + 0xBFC7E56D71D97C67,0xDDE6B2FF4F21D549,0x3C276B463AE86003,0x91767B4FAF86C71F, + 0x68A13E7835D4B9A0,0xB68C115F030C9FD4,0x141DD2C916582001,0x983D8F7DDD5324AC, + 0x64AA703FCC175254,0xC2C989948E02B426,0x3E5E76D69F46C2DE,0x50746F03587D8004, + 0x45DB3D829272F1E5,0x60584A029B560BF3,0xFBAE58A73FFCDC62,0xA15A5E4E6CAD4CE8, + 0x4BA96E55CE1FB8CC,0x08F9747AAE82B253,0xC102144CF7FB471B,0x9F042898F3EB8E36, + 0x068B27ADF2EFFB7A,0xEDCA97FE8C0A5EBE,0x778E0513F4F7D8CF,0x302C2501C32B8BF7, + 0x8D92DDFC175C554D,0xF865C57F46052F5F,0xEAF3301BA2B2F424,0xAA68B7ECBBD60D86, + 0x998F0F350104754C,0x0000000000000000,0xF12E314D34D0CCEC,0x710522BE061823B5, + 0xAF280D9930C005C1,0x97FD5CE25D693C65,0x19A41CC633CC9A15,0x95844172F8C79EB8, + 0xDC5432B7937684A9,0x9436C13A2490CF58,0x802B13F332C8EF59,0xC442AE397CED4F5C, + 0xFA1CD8EFE3AB8D82,0xF2E5AC954D293FD1,0x6AD823E8907A1B7D,0x4D2249F83CF043B6, + 0x03CB9DD879F9F33D,0xDE2D2F2736D82674,0x2A43A41F891EE2DF,0x6F98999D1B6C133A, + 0xD4AD46CD3DF436FA,0xBB35DF50269825C0,0x964FDCAA813E6D85,0xEB41B0537EE5A5C4, + 0x0540BA758B160847,0xA41AE43BE7BB44AF,0xE3B8C429D0671797,0x819993BBEE9FBEB9, + 0xAE9A8DD1EC975421,0xF3572CDD917E6E31,0x6393D7DAE2AFF8CE,0x47A2201237DC5338, + 0xA32343DEC903EE35,0x79FC56C4A89A91E6,0x01B28048DC5751E0,0x1296F564E4B7DB7B, + 0x75F7188351597A12,0xDB6D9552BDCE2E33,0x1E9DBB231D74308F,0x520D7293FDD322D9, + 0xE20A44610C304677,0xFEEEE2D2B4EAD425,0xCA30FDEE20800675,0x61EACA4A47015A13, + 0xE74AFE1487264E30,0x2CC883B27BF119A5,0x1664CF59B3F682DC,0xA811AA7C1E78AF5B, + 0x1D5626FB648DC3B2,0xB73E9117DF5BCE34,0xD05F7CF06AB56F5D,0xFD257F0ACD132718, + 0x574DC8E676C52A9E,0x0739A7E52EB8AA9A,0x5486553E0F3CD9A3,0x56FF48AEAA927B7E, + 0xBE756525AD8E2D87,0x7D0E6CF9FFDBC841,0x3B1ECCA31450CA99,0x6913BE30E983E840, + 0xAD511009956EA71C,0xB1B5B6BA2DB4354E,0x4469BDCA4E25A005,0x15AF5281CA0F71E1, + 0x744598CB8D0E2BF2,0x593F9B312AA863B7,0xEFB38A6E29A4FC63,0x6B6AA3A04C2D4A9D, + 0x3D95EB0EE6BF31E3,0xA291C3961554BFD5,0x18169C8EEF9BCBF5,0x115D68BC9D4E2846, + 0xBA875F18FACF7420,0xD1EDFCB8B6E23EBD,0xB00736F2F1E364AE,0x84D929CE6589B6FE, + 0x70B7A2F6DA4F7255,0x0E7253D75C6D4929,0x04F23A3D574159A7,0x0A8069EA0B2C108E, + 0x49D073C56BB11A11,0x8AAB7A1939E4FFD7,0xCD095A0B0E38ACEF,0xC9FB60365979F548, + 0x92BDE697D67F3422,0xC78933E10514BC61,0xE1C1D9B975C9B54A,0xD2266160CF1BCD80, + 0x9A4492ED78FD8671,0xB3CCAB2A881A9793,0x72CEBF667FE1D088,0xD6D45B5D985A9427 +},{ + 0xC811A8058C3F55DE,0x65F5B43196B50619,0xF74F96B1D6706E43,0x859D1E8BCB43D336, + 0x5AAB8A85CCFA3D84,0xF9C7BF99C295FCFD,0xA21FD5A1DE4B630F,0xCDB3EF763B8B456D, + 0x803F59F87CF7C385,0xB27C73BE5F31913C,0x98E3AC6633B04821,0xBF61674C26B8F818, + 0x0FFBC995C4C130C8,0xAAA0862010761A98,0x6057F342210116AA,0xF63C760C0654CC35, + 0x2DDB45CC667D9042,0xBCF45A964BD40382,0x68E8A0C3EF3C6F3D,0xA7BD92D269FF73BC, + 0x290AE20201ED2287,0xB7DE34CDE885818F,0xD901EEA7DD61059B,0xD6FA273219A03553, + 0xD56F1AE874CCCEC9,0xEA31245C2E83F554,0x7034555DA07BE499,0xCE26D2AC56E7BEF7, + 0xFD161857A5054E38,0x6A0E7DA4527436D1,0x5BD86A381CDE9FF2,0xCAF7756231770C32, + 0xB09AAED9E279C8D0,0x5DEF1091C60674DB,0x111046A2515E5045,0x23536CE4729802FC, + 0xC50CBCF7F5B63CFA,0x73A16887CD171F03,0x7D2941AFD9F28DBD,0x3F5E3EB45A4F3B9D, + 0x84EEFE361B677140,0x3DB8E3D3E7076271,0x1A3A28F9F20FD248,0x7EBC7C75B49E7627, + 0x74E5F293C7EB565C,0x18DCF59E4F478BA4,0x0C6EF44FA9ADCB52,0xC699812D98DAC760, + 0x788B06DC6E469D0E,0xFC65F8EA7521EC4E,0x30A5F7219E8E0B55,0x2BEC3F65BCA57B6B, + 0xDDD04969BAF1B75E,0x99904CDBE394EA57,0x14B201D1E6EA40F6,0xBBB0C08241284ADD, + 0x50F20463BF8F1DFF,0xE8D7F93B93CBACB8,0x4D8CB68E477C86E8,0xC1DD1B3992268E3F, + 0x7C5AA11209D62FCB,0x2F3D98ABDB35C9AE,0x671369562BFD5FF5,0x15C1E16C36CEE280, + 0x1D7EB2EDF8F39B17,0xDA94D37DB00DFE01,0x877BC3EC760B8ADA,0xCB8495DFE153AE44, + 0x05A24773B7B410B3,0x12857B783C32ABDF,0x8EB770D06812513B,0x536739B9D2E3E665, + 0x584D57E271B26468,0xD789C78FC9849725,0xA935BBFA7D1AE102,0x8B1537A3DFA64188, + 0xD0CD5D9BC378DE7A,0x4AC82C9A4D80CFB7,0x42777F1B83BDB620,0x72D2883A1D33BD75, + 0x5E7A2D4BAB6A8F41,0xF4DAAB6BBB1C95D9,0x905CFFE7FD8D31B6,0x83AA6422119B381F, + 0xC0AEFB8442022C49,0xA0F908C663033AE3,0xA428AF0804938826,0xADE41C341A8A53C7, + 0xAE7121EE77E6A85D,0xC47F5C4A25929E8C,0xB538E9AA55CDD863,0x06377AA9DAD8EB29, + 0xA18AE87BB3279895,0x6EDFDA6A35E48414,0x6B7D9D19825094A7,0xD41CFA55A4E86CBF, + 0xE5CAEDC9EA42C59C,0xA36C351C0E6FC179,0x5181E4DE6FABBF89,0xFFF0C530184D17D4, + 0x9D41EB1584045892,0x1C0D525028D73961,0xF178EC180CA8856A,0x9A0571018EF811CD, + 0x4091A27C3EF5EFCC,0x19AF15239F6329D2,0x347450EFF91EB990,0xE11B4A078DD27759, + 0xB9561DE5FC601331,0x912F1F5A2DA993C0,0x1654DCB65BA2191A,0x3E2DDE098A6B99EB, + 0x8A66D71E0F82E3FE,0x8C51ADB7D55A08D7,0x4533E50F8941FF7F,0x02E6DD67BD4859EC, + 0xE068AABA5DF6D52F,0xC24826E3FF4A75A5,0x6C39070D88ACDDF8,0x6486548C4691A46F, + 0xD1BEBD26135C7C0C,0xB30F93038F15334A,0x82D9849FC1BF9A69,0x9C320BA85420FAE4, + 0xFA528243AFF90767,0x9ED4D6CFE968A308,0xB825FD582C44B147,0x9B7691BC5EDCB3BB, + 0xC7EA619048FE6516,0x1063A61F817AF233,0x47D538683409A693,0x63C2CE984C6DED30, + 0x2A9FDFD86C81D91D,0x7B1E3B06032A6694,0x666089EBFBD9FD83,0x0A598EE67375207B, + 0x07449A140AFC495F,0x2CA8A571B6593234,0x1F986F8A45BBC2FB,0x381AA4A050B372C2, + 0x5423A3ADD81FAF3A,0x17273C0B8B86BB6C,0xFE83258DC869B5A2,0x287902BFD1C980F1, + 0xF5A94BD66B3837AF,0x88800A79B2CABA12,0x55504310083B0D4C,0xDF36940E07B9EEB2, + 0x04D1A7CE6790B2C5,0x612413FFF125B4DC,0x26F12B97C52C124F,0x86082351A62F28AC, + 0xEF93632F9937E5E7,0x3507B052293A1BE6,0xE72C30AE570A9C70,0xD3586041AE1425E0, + 0xDE4574B3D79D4CC4,0x92BA228040C5685A,0xF00B0CA5DC8C271C,0xBE1287F1F69C5A6E, + 0xF39E317FB1E0DC86,0x495D114020EC342D,0x699B407E3F18CD4B,0xDCA3A9D46AD51528, + 0x0D1D14F279896924,0x0000000000000000,0x593EB75FA196C61E,0x2E4E78160B116BD8, + 0x6D4AE7B058887F8E,0xE65FD013872E3E06,0x7A6DDBBBD30EC4E2,0xAC97FC89CAAEF1B1, + 0x09CCB33C1E19DBE1,0x89F3EAC462EE1864,0x7770CF49AA87ADC6,0x56C57ECA6557F6D6, + 0x03953DDA6D6CFB9A,0x36928D884456E07C,0x1EEB8F37959F608D,0x31D6179C4EAAA923, + 0x6FAC3AD7E5C02662,0x43049FA653991456,0xABD3669DC052B8EE,0xAF02C153A7C20A2B, + 0x3CCB036E3723C007,0x93C9C23D90E1CA2C,0xC33BC65E2F6ED7D3,0x4CFF56339758249E, + 0xB1E94E64325D6AA6,0x37E16D359472420A,0x79F8E661BE623F78,0x5214D90402C74413, + 0x482EF1FDF0C8965B,0x13F69BC5EC1609A9,0x0E88292814E592BE,0x4E198B542A107D72, + 0xCCC00FCBEBAFE71B,0x1B49C844222B703E,0x2564164DA840E9D5,0x20C6513E1FF4F966, + 0xBAC3203F910CE8AB,0xF2EDD1C261C47EF0,0x814CB945ACD361F3,0x95FEB8944A392105, + 0x5C9CF02C1622D6AD,0x971865F3F77178E9,0xBD87BA2B9BF0A1F4,0x444005B259655D09, + 0xED75BE48247FBC0B,0x7596122E17CFF42A,0xB44B091785E97A15,0x966B854E2755DA9F, + 0xEEE0839249134791,0x32432A4623C652B9,0xA8465B47AD3E4374,0xF8B45F2412B15E8B, + 0x2417F6F078644BA3,0xFB2162FE7FDDA511,0x4BBBCC279DA46DC1,0x0173E0BDD024A276, + 0x22208C59A2BCA08A,0x8FC4906DB836F34D,0xE4B90D743A6667EA,0x7147B5E0705F46EF, + 0x2782CB2A1508B039,0xEC065EF5F45B1E7D,0x21B5B183CFD05B10,0xDBE733C060295C77, + 0x9FA73672394C017E,0xCF55321186C31C81,0xD8720E1A0D45A7ED,0x3B8F997A3DDF8958, + 0x3AFC79C7EDFB2B2E,0xE9A4198643EF0ECE,0x5F09CDF67B4E2D37,0x4F6A6BE9FA34DF04, + 0xB6ADD47038A123F9,0x8D224D0A057EAAA1,0xC96248B85C1BF7A8,0xE3FD9760309A2EB5, + 0x0B2A6E5BA351820D,0xEB42C4E1FEA75722,0x948D58299A1D8373,0x7FCF9CC864BAD451, + 0xA55B4FB5D4B72A50,0x08BF5381CE3D7997,0x46A6D8D5E42D04E5,0xD22B80FC7E308796, + 0x57B69E77B57354A0,0x3969441D8097D0B4,0x3330CAFBF3E2F0CF,0xE28E77DDE0BE8CC3, + 0x62B12E259C494F46,0xA6CE726FB9DBD1CA,0x41E242C1EED14DBA,0x76032FF47AA30FB0 +},{ + 0x45B268A93ACDE4CC,0xAF7F0BE884549D08,0x048354B3C1468263,0x925435C2C80EFED2, + 0xEE4E37F27FDFFBA7,0x167A33920C60F14D,0xFB123B52EA03E584,0x4A0CAB53FDBB9007, + 0x9DEAF6380F788A19,0xCB48EC558F0CB32A,0xB59DC4B2D6FEF7E0,0xDCDBCA22F4F3ECB6, + 0x11DF5813549A9C40,0xE33FDEDF568ACED3,0xA0C1C8124322E9C3,0x07A56B8158FA6D0D, + 0x77279579B1E1F3DD,0xD9B18B74422AC004,0xB8EC2D9FFFABC294,0xF4ACF8A82D75914F, + 0x7BBF69B1EF2B6878,0xC4F62FAF487AC7E1,0x76CE809CC67E5D0C,0x6711D88F92E4C14C, + 0x627B99D9243DEDFE,0x234AA5C3DFB68B51,0x909B1F15262DBF6D,0x4F66EA054B62BCB5, + 0x1AE2CF5A52AA6AE8,0xBEA053FBD0CE0148,0xED6808C0E66314C9,0x43FE16CD15A82710, + 0xCD049231A06970F6,0xE7BC8A6C97CC4CB0,0x337CE835FCB3B9C0,0x65DEF2587CC780F3, + 0x52214EDE4132BB50,0x95F15E4390F493DF,0x870839625DD2E0F1,0x41313C1AFB8B66AF, + 0x91720AF051B211BC,0x477D427ED4EEA573,0x2E3B4CEEF6E3BE25,0x82627834EB0BCC43, + 0x9C03E3DD78E724C8,0x2877328AD9867DF9,0x14B51945E243B0F2,0x574B0F88F7EB97E2, + 0x88B6FA989AA4943A,0x19C4F068CB168586,0x50EE6409AF11FAEF,0x7DF317D5C04EABA4, + 0x7A567C5498B4C6A9,0xB6BBFB804F42188E,0x3CC22BCF3BC5CD0B,0xD04336EAAA397713, + 0xF02FAC1BEC33132C,0x2506DBA7F0D3488D,0xD7E65D6BF2C31A1E,0x5EB9B2161FF820F5, + 0x842E0650C46E0F9F,0x716BEB1D9E843001,0xA933758CAB315ED4,0x3FE414FDA2792265, + 0x27C9F1701EF00932,0x73A4C1CA70A771BE,0x94184BA6E76B3D0E,0x40D829FF8C14C87E, + 0x0FBEC3FAC77674CB,0x3616A9634A6A9572,0x8F139119C25EF937,0xF545ED4D5AEA3F9E, + 0xE802499650BA387B,0x6437E7BD0B582E22,0xE6559F89E053E261,0x80AD52E305288DFC, + 0x6DC55A23E34B9935,0xDE14E0F51AD0AD09,0xC6390578A659865E,0x96D7617109487CB1, + 0xE2D6CB3A21156002,0x01E915E5779FAED1,0xADB0213F6A77DCB7,0x9880B76EB9A1A6AB, + 0x5D9F8D248644CF9B,0xFD5E4536C5662658,0xF1C6B9FE9BACBDFD,0xEACD6341BE9979C4, + 0xEFA7221708405576,0x510771ECD88E543E,0xC2BA51CB671F043D,0x0AD482AC71AF5879, + 0xFE787A045CDAC936,0xB238AF338E049AED,0xBD866CC94972EE26,0x615DA6EBBD810290, + 0x3295FDD08B2C1711,0xF834046073BF0AEA,0xF3099329758FFC42,0x1CAEB13E7DCFA934, + 0xBA2307481188832B,0x24EFCE42874CE65C,0x0E57D61FB0E9DA1A,0xB3D1BAD6F99B343C, + 0xC0757B1C893C4582,0x2B510DB8403A9297,0x5C7698C1F1DB614A,0x3E0D0118D5E68CB4, + 0xD60F488E855CB4CF,0xAE961E0DF3CB33D9,0x3A8E55AB14A00ED7,0x42170328623789C1, + 0x838B6DD19C946292,0x895FEF7DED3B3AEB,0xCFCBB8E64E4A3149,0x064C7E642F65C3DC, + 0x3D2B3E2A4C5A63DA,0x5BD3F340A9210C47,0xB474D157A1615931,0xAC5934DA1DE87266, + 0x6EE365117AF7765B,0xC86ED36716B05C44,0x9BA6885C201D49C5,0xB905387A88346C45, + 0x131072C4BAB9DDFF,0xBF49461EA751AF99,0xD52977BC1CE05BA1,0xB0F785E46027DB52, + 0x546D30BA6E57788C,0x305AD707650F56AE,0xC987C682612FF295,0xA5AB8944F5FBC571, + 0x7ED528E759F244CA,0x8DDCBBCE2C7DB888,0xAA154ABE328DB1BA,0x1E619BE993ECE88B, + 0x09F2BD9EE813B717,0x7401AA4B285D1CB3,0x21858F143195CAEE,0x48C381841398D1B8, + 0xFCB750D3B2F98889,0x39A86A998D1CE1B9,0x1F888E0CE473465A,0x7899568376978716, + 0x02CF2AD7EE2341BF,0x85C713B5B3F1A14E,0xFF916FE12B4567E7,0x7C1A0230B7D10575, + 0x0C98FCC85ECA9BA5,0xA3E7F720DA9E06AD,0x6A6031A2BBB1F438,0x973E74947ED7D260, + 0x2CF4663918C0FF9A,0x5F50A7F368678E24,0x34D983B4A449D4CD,0x68AF1B755592B587, + 0x7F3C3D022E6DEA1B,0xABFC5F5B45121F6B,0x0D71E92D29553574,0xDFFDF5106D4F03D8, + 0x081BA87B9F8C19C6,0xDB7EA1A3AC0981BB,0xBBCA12AD66172DFA,0x79704366010829C7, + 0x179326777BFF5F9C,0x0000000000000000,0xEB2476A4C906D715,0x724DD42F0738DF6F, + 0xB752EE6538DDB65F,0x37FFBC863DF53BA3,0x8EFA84FCB5C157E6,0xE9EB5C73272596AA, + 0x1B0BDABF2535C439,0x86E12C872A4D4E20,0x9969A28BCE3E087A,0xFAFB2EB79D9C4B55, + 0x056A4156B6D92CB2,0x5A3AE6A5DEBEA296,0x22A3B026A8292580,0x53C85B3B36AD1581, + 0xB11E900117B87583,0xC51F3A4A3FE56930,0xE019E1EDCF3621BD,0xEC811D2591FCBA18, + 0x445B7D4C4D524A1D,0xA8DA6069DCAEF005,0x58F5CC72309DE329,0xD4C062596B7FF570, + 0xCE22AD0339D59F98,0x591CD99747024DF8,0x8B90C5AA03187B54,0xF663D27FC356D0F0, + 0xD8589E9135B56ED5,0x35309651D3D67A1C,0x12F96721CD26732E,0xD28C1C3D441A36AC, + 0x492A946164077F69,0x2D1D73DC6F5F514B,0x6F0A70F40D68D88A,0x60B4B30ECA1EAC41, + 0xD36509D83385987D,0x0B3D97490630F6A8,0x9ECCC90A96C46577,0xA20EE2C5AD01A87C, + 0xE49AB55E0E70A3DE,0xA4429CA182646BA0,0xDA97B446DB962F6A,0xCCED87D4D7F6DE27, + 0x2AB8185D37A53C46,0x9F25DCEFE15BCBA6,0xC19C6EF9FEA3EB53,0xA764A3931BD884CE, + 0x2FD2590B817C10F4,0x56A21A6D80743933,0xE573A0BB79EF0D0F,0x155C0CA095DC1E23, + 0x6C2C4FC694D437E4,0x10364DF623053291,0xDD32DFC7836C4267,0x03263F3299BCEF6E, + 0x66F8CD6AE57B6F9D,0x8C35AE2B5BE21659,0x31B3C2E21290F87F,0x93BD2027BF915003, + 0x69460E90220D1B56,0x299E276FAE19D328,0x63928C3C53A2432F,0x7082FEF8E91B9ED0, + 0xBC6F792C3EED40F7,0x4C40D537D2DE53DB,0x75E8BFAE5FC2B262,0x4DA9C0D2A541FD0A, + 0x4E8FFFE03CFD1264,0x2620E495696FA7E3,0xE1F0F408B8A98F6C,0xD1AA230FDDA6D9C2, + 0xC7D0109DD1C6288F,0x8A79D04F7487D585,0x4694579BA3710BA2,0x38417F7CFA834F68, + 0x1D47A4DB0A5007E5,0x206C9AF1460A643F,0xA128DDF734BD4712,0x8144470672B7232D, + 0xF2E086CC02105293,0x182DE58DBC892B57,0xCAA1F9B0F8931DFB,0x6B892447CC2E5AE9, + 0xF9DD11850420A43B,0x4BE5BEB68A243ED6,0x5584255F19C8D65D,0x3B67404E633FA006, + 0xA68DB6766C472A1F,0xF78AC79AB4C97E21,0xC353442E1080AAEC,0x9A4F9DB95782E714 +},{ + 0x05BA7BC82C9B3220,0x31A54665F8B65E4F,0xB1B651F77547F4D4,0x8BFA0D857BA46682, + 0x85A96C5AA16A98BB,0x990FAEF908EB79C9,0xA15E37A247F4A62D,0x76857DCD5D27741E, + 0xF8C50B800A1820BC,0xBE65DCB201F7A2B4,0x666D1B986F9426E7,0x4CC921BF53C4E648, + 0x95410A0F93D9CA42,0x20CDCCAA647BA4EF,0x429A4060890A1871,0x0C4EA4F69B32B38B, + 0xCCDA362DDE354CD3,0x96DC23BC7C5B2FA9,0xC309BB68AA851AB3,0xD26131A73648E013, + 0x021DC52941FC4DB2,0xCD5ADAB7704BE48A,0xA77965D984ED71E6,0x32386FD61734BBA4, + 0xE82D6DD538AB7245,0x5C2147EA6177B4B1,0x5DA1AB70CF091CE8,0xAC907FCE72B8BDFF, + 0x57C85DFD972278A8,0xA4E44C6A6B6F940D,0x3851995B4F1FDFE4,0x62578CCAED71BC9E, + 0xD9882BB0C01D2C0A,0x917B9D5D113C503B,0xA2C31E11A87643C6,0xE463C923A399C1CE, + 0xF71686C57EA876DC,0x87B4A973E096D509,0xAF0D567D9D3A5814,0xB40C2A3F59DCC6F4, + 0x3602F88495D121DD,0xD3E1DD3D9836484A,0xF945E71AA46688E5,0x7518547EB2A591F5, + 0x9366587450C01D89,0x9EA81018658C065B,0x4F54080CBC4603A3,0x2D0384C65137BF3D, + 0xDC325078EC861E2A,0xEA30A8FC79573FF7,0x214D2030CA050CB6,0x65F0322B8016C30C, + 0x69BE96DD1B247087,0xDB95EE9981E161B8,0xD1FC1814D9CA05F8,0x820ED2BBCC0DE729, + 0x63D76050430F14C7,0x3BCCB0E8A09D3A0F,0x8E40764D573F54A2,0x39D175C1E16177BD, + 0x12F5A37C734F1F4B,0xAB37C12F1FDFC26D,0x5648B167395CD0F1,0x6C04ED1537BF42A7, + 0xED97161D14304065,0x7D6C67DAAB72B807,0xEC17FA87BA4EE83C,0xDFAF79CB0304FBC1, + 0x733F060571BC463E,0x78D61C1287E98A27,0xD07CF48E77B4ADA1,0xB9C262536C90DD26, + 0xE2449B5860801605,0x8FC09AD7F941FCFB,0xFAD8CEA94BE46D0E,0xA343F28B0608EB9F, + 0x9B126BD04917347B,0x9A92874AE7699C22,0x1B017C42C4E69EE0,0x3A4C5C720EE39256, + 0x4B6E9F5E3EA399DA,0x6BA353F45AD83D35,0xE7FEE0904C1B2425,0x22D009832587E95D, + 0x842980C00F1430E2,0xC6B3C0A0861E2893,0x087433A419D729F2,0x341F3DADD42D6C6F, + 0xEE0A3FAEFBB2A58E,0x4AEE73C490DD3183,0xAAB72DB5B1A16A34,0xA92A04065E238FDF, + 0x7B4B35A1686B6FCC,0x6A23BF6EF4A6956C,0x191CB96B851AD352,0x55D598D4D6DE351A, + 0xC9604DE5F2AE7EF3,0x1CA6C2A3A981E172,0xDE2F9551AD7A5398,0x3025AAFF56C8F616, + 0x15521D9D1E2860D9,0x506FE31CFA45073A,0x189C55F12B647B0B,0x0180EC9AAE7EA859, + 0x7CEC8B40050C105E,0x2350E5198BF94104,0xEF8AD33455CC0DD7,0x07A7BEE16D677F92, + 0xE5E325B90DE76997,0x5A061591A26E637A,0xB611EF1618208B46,0x09F4DF3EB7A981AB, + 0x1EBB078AE87DACC0,0xB791038CB65E231F,0x0FD38D4574B05660,0x67EDF702C1EA8EBE, + 0xBA5F4BE0831238CD,0xE3C477C2CEFEBE5C,0x0DCE486C354C1BD2,0x8C5DB36416C31910, + 0x26EA9ED1A7627324,0x039D29B3EF82E5EB,0x9F28FC82CBF2AE02,0xA8AAE89CF05D2786, + 0x431AACFA2774B028,0xCF471F9E31B7A938,0x581BD0B8E3922EC8,0xBC78199B400BEF06, + 0x90FB71C7BF42F862,0x1F3BEB1046030499,0x683E7A47B55AD8DE,0x988F4263A695D190, + 0xD808C72A6E638453,0x0627527BC319D7CB,0xEBB04466D72997AE,0xE67E0C0AE2658C7C, + 0x14D2F107B056C880,0x7122C32C30400B8C,0x8A7AE11FD5DACEDB,0xA0DEDB38E98A0E74, + 0xAD109354DCC615A6,0x0BE91A17F655CC19,0x8DDD5FFEB8BDB149,0xBFE53028AF890AED, + 0xD65BA6F5B4AD7A6A,0x7956F0882997227E,0x10E8665532B352F9,0x0E5361DFDACEFE39, + 0xCEC7F3049FC90161,0xFF62B561677F5F2E,0x975CCF26D22587F0,0x51EF0F86543BAF63, + 0x2F1E41EF10CBF28F,0x52722635BBB94A88,0xAE8DBAE73344F04D,0x410769D36688FD9A, + 0xB3AB94DE34BBB966,0x801317928DF1AA9B,0xA564A0F0C5113C54,0xF131D4BEBDB1A117, + 0x7F71A2F3EA8EF5B5,0x40878549C8F655C3,0x7EF14E6944F05DEC,0xD44663DCF55137D8, + 0xF2ACFD0D523344FC,0x0000000000000000,0x5FBC6E598EF5515A,0x16CF342EF1AA8532, + 0xB036BD6DDB395C8D,0x13754FE6DD31B712,0xBBDFA77A2D6C9094,0x89E7C8AC3A582B30, + 0x3C6B0E09CDFA459D,0xC4AE0589C7E26521,0x49735A777F5FD468,0xCAFD64561D2C9B18, + 0xDA1502032F9FC9E1,0x8867243694268369,0x3782141E3BAF8984,0x9CB5D53124704BE9, + 0xD7DB4A6F1AD3D233,0xA6F989432A93D9BF,0x9D3539AB8A0EE3B0,0x53F2CAAF15C7E2D1, + 0x6E19283C76430F15,0x3DEBE2936384EDC4,0x5E3C82C3208BF903,0x33B8834CB94A13FD, + 0x6470DEB12E686B55,0x359FD1377A53C436,0x61CAA57902F35975,0x043A975282E59A79, + 0xFD7F70482683129C,0xC52EE913699CCD78,0x28B9FF0E7DAC8D1D,0x5455744E78A09D43, + 0xCB7D88CCB3523341,0x44BD121B4A13CFBA,0x4D49CD25FDBA4E11,0x3E76CB208C06082F, + 0x3FF627BA2278A076,0xC28957F204FBB2EA,0x453DFE81E46D67E3,0x94C1E6953DA7621B, + 0x2C83685CFF491764,0xF32C1197FC4DECA5,0x2B24D6BD922E68F6,0xB22B78449AC5113F, + 0x48F3B6EDD1217C31,0x2E9EAD75BEB55AD6,0x174FD8B45FD42D6B,0x4ED4E4961238ABFA, + 0x92E6B4EEFEBEB5D0,0x46A0D7320BEF8208,0x47203BA8A5912A51,0x24F75BF8E69E3E96, + 0xF0B1382413CF094E,0xFEE259FBC901F777,0x276A724B091CDB7D,0xBDF8F501EE75475F, + 0x599B3C224DEC8691,0x6D84018F99C1EAFE,0x7498B8E41CDB39AC,0xE0595E71217C5BB7, + 0x2AA43A273C50C0AF,0xF50B43EC3F543B6E,0x838E3E2162734F70,0xC09492DB4507FF58, + 0x72BFEA9FDFC2EE67,0x11688ACF9CCDFAA0,0x1A8190D86A9836B9,0x7ACBD93BC615C795, + 0xC7332C3A286080CA,0x863445E94EE87D50,0xF6966A5FD0D6DE85,0xE9AD814F96D5DA1C, + 0x70A22FB69E3EA3D5,0x0A69F68D582B6440,0xB8428EC9C2EE757F,0x604A49E3AC8DF12C, + 0x5B86F90B0C10CB23,0xE1D9B2EB8F02F3EE,0x29391394D3D22544,0xC8E0A17F5CD0D6AA, + 0xB58CC6A5F7A26EAD,0x8193FB08238F02C2,0xD5C68F465B2F9F81,0xFCFF9CD288FDBAC5, + 0x77059157F359DC47,0x1D262E3907FF492B,0xFB582233E59AC557,0xDDB2BCE242F8B673, + 0x2577B76248E096CF,0x6F99C4A6D83DA74C,0xC1147E41EB795701,0xF48BAF76912A9337 +},{ + 0x3EF29D249B2C0A19,0xE9E16322B6F8622F,0x5536994047757F7A,0x9F4D56D5A47B0B33, + 0x822567466AA1174C,0xB8F5057DEB082FB2,0xCC48C10BF4475F53,0x373088D4275DEC3A, + 0x968F4325180AED10,0x173D232CF7016151,0xAE4ED09F946FCC13,0xFD4B4741C4539873, + 0x1B5B3F0DD9933765,0x2FFCB0967B644052,0xE02376D20A89840C,0xA3AE3A70329B18D7, + 0x419CBD2335DE8526,0xFAFEBF115B7C3199,0x0397074F85AA9B0D,0xC58AD4FB4836B970, + 0xBEC60BE3FC4104A8,0x1EFF36DC4B708772,0x131FDC33ED8453B6,0x0844E33E341764D3, + 0x0FF11B6EAB38CD39,0x64351F0A7761B85A,0x3B5694F509CFBA0E,0x30857084B87245D0, + 0x47AFB3BD2297AE3C,0xF2BA5C2F6F6B554A,0x74BDC4761F4F70E1,0xCFDFC64471EDC45E, + 0xE610784C1DC0AF16,0x7ACA29D63C113F28,0x2DED411776A859AF,0xAC5F211E99A3D5EE, + 0xD484F949A87EF33B,0x3CE36CA596E013E4,0xD120F0983A9D432C,0x6BC40464DC597563, + 0x69D5F5E5D1956C9E,0x9AE95F043698BB24,0xC9ECC8DA66A4EF44,0xD69508C8A5B2EAC6, + 0xC40C2235C0503B80,0x38C193BA8C652103,0x1CEEC75D46BC9E8F,0xD331011937515AD1, + 0xD8E2E56886ECA50F,0xB137108D5779C991,0x709F3B6905CA4206,0x4FEB50831680CAEF, + 0xEC456AF3241BD238,0x58D673AFE181ABBE,0x242F54E7CAD9BF8C,0x0211F1810DCC19FD, + 0x90BC4DBB0F43C60A,0x9518446A9DA0761D,0xA1BFCBF13F57012A,0x2BDE4F8961E172B5, + 0x27B853A84F732481,0xB0B1E643DF1F4B61,0x18CC38425C39AC68,0xD2B7F7D7BF37D821, + 0x3103864A3014C720,0x14AA246372ABFA5C,0x6E600DB54EBAC574,0x394765740403A3F3, + 0x09C215F0BC71E623,0x2A58B947E987F045,0x7B4CDF18B477BDD8,0x9709B5EB906C6FE0, + 0x73083C268060D90B,0xFEDC400E41F9037E,0x284948C6E44BE9B8,0x728ECAE808065BFB, + 0x06330E9E17492B1A,0x5950856169E7294E,0xBAE4F4FCE6C4364F,0xCA7BCF95E30E7449, + 0x7D7FD186A33E96C2,0x52836110D85AD690,0x4DFAA1021B4CD312,0x913ABB75872544FA, + 0xDD46ECB9140F1518,0x3D659A6B1E869114,0xC23F2CABD719109A,0xD713FE062DD46836, + 0xD0A60656B2FBC1DC,0x221C5A79DD909496,0xEFD26DBCA1B14935,0x0E77EDA0235E4FC9, + 0xCBFD395B6B68F6B9,0x0DE0EAEFA6F4D4C4,0x0422FF1F1A8532E7,0xF969B85EDED6AA94, + 0x7F6E2007AEF28F3F,0x3AD0623B81A938FE,0x6624EE8B7AADA1A7,0xB682E8DDC856607B, + 0xA78CC56F281E2A30,0xC79B257A45FAA08D,0x5B4174E0642B30B3,0x5F638BFF7EAE0254, + 0x4BC9AF9C0C05F808,0xCE59308AF98B46AE,0x8FC58DA9CC55C388,0x803496C7676D0EB1, + 0xF33CAAE1E70DD7BA,0xBB6202326EA2B4BF,0xD5020F87201871CB,0x9D5CA754A9B712CE, + 0x841669D87DE83C56,0x8A6184785EB6739F,0x420BBA6CB0741E2B,0xF12D5B60EAC1CE47, + 0x76AC35F71283691C,0x2C6BB7D9FECEDB5F,0xFCCDB18F4C351A83,0x1F79C012C3160582, + 0xF0ABADAE62A74CB7,0xE1A5801C82EF06FC,0x67A21845F2CB2357,0x5114665F5DF04D9D, + 0xBF40FD2D74278658,0xA0393D3FB73183DA,0x05A409D192E3B017,0xA9FB28CF0B4065F9, + 0x25A9A22942BF3D7C,0xDB75E22703463E02,0xB326E10C5AB5D06C,0xE7968E8295A62DE6, + 0xB973F3B3636EAD42,0xDF571D3819C30CE5,0xEE549B7229D7CBC5,0x12992AFD65E2D146, + 0xF8EF4E9056B02864,0xB7041E134030E28B,0xC02EDD2ADAD50967,0x932B4AF48AE95D07, + 0x6FE6FB7BC6DC4784,0x239AACB755F61666,0x401A4BEDBDB807D6,0x485EA8D389AF6305, + 0xA41BC220ADB4B13D,0x753B32B89729F211,0x997E584BB3322029,0x1D683193CEDA1C7F, + 0xFF5AB6C0C99F818E,0x16BBD5E27F67E3A1,0xA59D34EE25D233CD,0x98F8AE853B54A2D9, + 0x6DF70AFACB105E79,0x795D2E99B9BBA425,0x8E437B6744334178,0x0186F6CE886682F0, + 0xEBF092A3BB347BD2,0xBCD7FA62F18D1D55,0xADD9D7D011C5571E,0x0BD3E471B1BDFFDE, + 0xAA6C2F808EEAFEF4,0x5EE57D31F6C880A4,0xF50FA47FF044FCA0,0x1ADDC9C351F5B595, + 0xEA76646D3352F922,0x0000000000000000,0x85909F16F58EBEA6,0x46294573AAF12CCC, + 0x0A5512BF39DB7D2E,0x78DBD85731DD26D5,0x29CFBE086C2D6B48,0x218B5D36583A0F9B, + 0x152CD2ADFACD78AC,0x83A39188E2C795BC,0xC3B9DA655F7F926A,0x9ECBA01B2C1D89C3, + 0x07B5F8509F2FA9EA,0x7EE8D6C926940DCF,0x36B67E1AAF3B6ECA,0x86079859702425AB, + 0xFB7849DFD31AB369,0x4C7C57CC932A51E2,0xD96413A60E8A27FF,0x263EA566C715A671, + 0x6C71FC344376DC89,0x4A4F595284637AF8,0xDAF314E98B20BCF2,0x572768C14AB96687, + 0x1088DB7C682EC8BB,0x887075F9537A6A62,0x2E7A4658F302C2A2,0x619116DBE582084D, + 0xA87DDE018326E709,0xDCC01A779C6997E8,0xEDC39C3DAC7D50C8,0xA60A33A1A078A8C0, + 0xC1A82BE452B38B97,0x3F746BEA134A88E9,0xA228CCBEBAFD9A27,0xABEAD94E068C7C04, + 0xF48952B178227E50,0x5CF48CB0FB049959,0x6017E0156DE48ABD,0x4438B4F2A73D3531, + 0x8C528AE649FF5885,0xB515EF924DFCFB76,0x0C661C212E925634,0xB493195CC59A7986, + 0x9CDA519A21D1903E,0x32948105B5BE5C2D,0x194ACE8CD45F2E98,0x438D4CA238129CDB, + 0x9B6FA9CABEFE39D4,0x81B26009EF0B8C41,0xDED1EBF691A58E15,0x4E6DA64D9EE6481F, + 0x54B06F8ECF13FD8A,0x49D85E1D01C9E1F5,0xAFC826511C094EE3,0xF698A33075EE67AD, + 0x5AC7822EEC4DB243,0x8DD47C28C199DA75,0x89F68337DB1CE892,0xCDCE37C57C21DDA3, + 0x530597DE503C5460,0x6A42F2AA543FF793,0x5D727A7E73621BA9,0xE232875307459DF1, + 0x56A19E0FC2DFE477,0xC61DD3B4CD9C227D,0xE5877F03986A341B,0x949EB2A415C6F4ED, + 0x6206119460289340,0x6380E75AE84E11B0,0x8BE772B6D6D0F16F,0x50929091D596CF6D, + 0xE86795EC3E9EE0DF,0x7CF927482B581432,0xC86A3E14EEC26DB4,0x7119CDA78DACC0F6, + 0xE40189CD100CB6EB,0x92ADBC3A028FDFF7,0xB2A017C2D2D3529C,0x200DABF8D05C8D6B, + 0x34A78F9BA2F77737,0xE3B4719D8F231F01,0x45BE423C2F5BB7C1,0xF71E55FEFD88E55D, + 0x6853032B59F3EE6E,0x65B3E9C4FF073AAA,0x772AC3399AE5EBEC,0x87816E97F842A75B, + 0x110E2DB2E0484A4B,0x331277CB3DD8DEDD,0xBD510CAC79EB9FA5,0x352179552A91F5C7 +},{ + 0x8AB0A96846E06A6D,0x43C7E80B4BF0B33A,0x08C9B3546B161EE5,0x39F1C235EBA990BE, + 0xC1BEF2376606C7B2,0x2C209233614569AA,0xEB01523B6FC3289A,0x946953AB935ACEDD, + 0x272838F63E13340E,0x8B0455ECA12BA052,0x77A1B2C4978FF8A2,0xA55122CA13E54086, + 0x2276135862D3F1CD,0xDB8DDFDE08B76CFE,0x5D1E12C89E4A178A,0x0E56816B03969867, + 0xEE5F79953303ED59,0xAFED748BAB78D71D,0x6D929F2DF93E53EE,0xF5D8A8F8BA798C2A, + 0xF619B1698E39CF6B,0x95DDAF2F749104E2,0xEC2A9C80E0886427,0xCE5C8FD8825B95EA, + 0xC4E0D9993AC60271,0x4699C3A5173076F9,0x3D1B151F50A29F42,0x9ED505EA2BC75946, + 0x34665ACFDC7F4B98,0x61B1FB53292342F7,0xC721C0080E864130,0x8693CD1696FD7B74, + 0x872731927136B14B,0xD3446C8A63A1721B,0x669A35E8A6680E4A,0xCAB658F239509A16, + 0xA4E5DE4EF42E8AB9,0x37A7435EE83F08D9,0x134E6239E26C7F96,0x82791A3C2DF67488, + 0x3F6EF00A8329163C,0x8E5A7E42FDEB6591,0x5CAAEE4C7981DDB5,0x19F234785AF1E80D, + 0x255DDDE3ED98BD70,0x50898A32A99CCCAC,0x28CA4519DA4E6656,0xAE59880F4CB31D22, + 0x0D9798FA37D6DB26,0x32F968F0B4FFCD1A,0xA00F09644F258545,0xFA3AD5175E24DE72, + 0xF46C547C5DB24615,0x713E80FBFF0F7E20,0x7843CF2B73D2AAFA,0xBD17EA36AEDF62B4, + 0xFD111BACD16F92CF,0x4ABAA7DBC72D67E0,0xB3416B5DAD49FAD3,0xBCA316B24914A88B, + 0x15D150068AECF914,0xE27C1DEBE31EFC40,0x4FE48C759BEDA223,0x7EDCFD141B522C78, + 0x4E5070F17C26681C,0xE696CAC15815F3BC,0x35D2A64B3BB481A7,0x800CFF29FE7DFDF6, + 0x1ED9FAC3D5BAA4B0,0x6C2663A91EF599D1,0x03C1199134404341,0xF7AD4DED69F20554, + 0xCD9D9649B61BD6AB,0xC8C3BDE7EADB1368,0xD131899FB02AFB65,0x1D18E352E1FAE7F1, + 0xDA39235AEF7CA6C1,0xA1BBF5E0A8EE4F7A,0x91377805CF9A0B1E,0x3138716180BF8E5B, + 0xD9F83ACBDB3CE580,0x0275E515D38B897E,0x472D3F21F0FBBCC6,0x2D946EB7868EA395, + 0xBA3C248D21942E09,0xE7223645BFDE3983,0xFF64FEB902E41BB1,0xC97741630D10D957, + 0xC3CB1722B58D4ECC,0xA27AEC719CAE0C3B,0x99FECB51A48C15FB,0x1465AC826D27332B, + 0xE1BD047AD75EBF01,0x79F733AF941960C5,0x672EC96C41A3C475,0xC27FEBA6524684F3, + 0x64EFD0FD75E38734,0xED9E60040743AE18,0xFB8E2993B9EF144D,0x38453EB10C625A81, + 0x6978480742355C12,0x48CF42CE14A6EE9E,0x1CAC1FD606312DCE,0x7B82D6BA4792E9BB, + 0x9D141C7B1F871A07,0x5616B80DC11C4A2E,0xB849C198F21FA777,0x7CA91801C8D9A506, + 0xB1348E487EC273AD,0x41B20D1E987B3A44,0x7460AB55A3CFBBE3,0x84E628034576F20A, + 0x1B87D16D897A6173,0x0FE27DEFE45D5258,0x83CDE6B8CA3DBEB7,0x0C23647ED01D1119, + 0x7A362A3EA0592384,0xB61F40F3F1893F10,0x75D457D1440471DC,0x4558DA34237035B8, + 0xDCA6116587FC2043,0x8D9B67D3C9AB26D0,0x2B0B5C88EE0E2517,0x6FE77A382AB5DA90, + 0x269CC472D9D8FE31,0x63C41E46FAA8CB89,0xB7ABBC771642F52F,0x7D1DE4852F126F39, + 0xA8C6BA3024339BA0,0x600507D7CEE888C8,0x8FEE82C61A20AFAE,0x57A2448926D78011, + 0xFCA5E72836A458F0,0x072BCEBB8F4B4CBD,0x497BBE4AF36D24A1,0x3CAFE99BB769557D, + 0x12FA9EBD05A7B5A9,0xE8C04BAA5B836BDB,0x4273148FAC3B7905,0x908384812851C121, + 0xE557D3506C55B0FD,0x72FF996ACB4F3D61,0x3EDA0C8E64E2DC03,0xF0868356E6B949E9, + 0x04EAD72ABB0B0FFC,0x17A4B5135967706A,0xE3C8E16F04D5367F,0xF84F30028DAF570C, + 0x1846C8FCBD3A2232,0x5B8120F7F6CA9108,0xD46FA231ECEA3EA6,0x334D947453340725, + 0x58403966C28AD249,0xBED6F3A79A9F21F5,0x68CCB483A5FE962D,0xD085751B57E1315A, + 0xFED0023DE52FD18E,0x4B0E5B5F20E6ADDF,0x1A332DE96EB1AB4C,0xA3CE10F57B65C604, + 0x108F7BA8D62C3CD7,0xAB07A3A11073D8E1,0x6B0DAD1291BED56C,0xF2F366433532C097, + 0x2E557726B2CEE0D4,0x0000000000000000,0xCB02A476DE9B5029,0xE4E32FD48B9E7AC2, + 0x734B65EE2C84F75E,0x6E5386BCCD7E10AF,0x01B4FC84E7CBCA3F,0xCFE8735C65905FD5, + 0x3613BFDA0FF4C2E6,0x113B872C31E7F6E8,0x2FE18BA255052AEB,0xE974B72EBC48A1E4, + 0x0ABC5641B89D979B,0xB46AA5E62202B66E,0x44EC26B0C4BBFF87,0xA6903B5B27A503C7, + 0x7F680190FC99E647,0x97A84A3AA71A8D9C,0xDD12EDE16037EA7C,0xC554251DDD0DC84E, + 0x88C54C7D956BE313,0x4D91696048662B5D,0xB08072CC9909B992,0xB5DE5962C5C97C51, + 0x81B803AD19B637C9,0xB2F597D94A8230EC,0x0B08AAC55F565DA4,0xF1327FD2017283D6, + 0xAD98919E78F35E63,0x6AB9519676751F53,0x24E921670A53774F,0xB9FD3D1C15D46D48, + 0x92F66194FBDA485F,0x5A35DC7311015B37,0xDED3F4705477A93D,0xC00A0EB381CD0D8D, + 0xBB88D809C65FE436,0x16104997BEACBA55,0x21B70AC95693B28C,0x59F4C5E225411876, + 0xD5DB5EB50B21F499,0x55D7A19CF55C096F,0xA97246B4C3F8519F,0x8552D487A2BD3835, + 0x54635D181297C350,0x23C2EFDC85183BF2,0x9F61F96ECC0C9379,0x534893A39DDC8FED, + 0x5EDF0B59AA0A54CB,0xAC2C6D1A9F38945C,0xD7AEBBA0D8AA7DE7,0x2ABFA00C09C5EF28, + 0xD84CC64F3CF72FBF,0x2003F64DB15878B3,0xA724C7DFC06EC9F8,0x069F323F68808682, + 0xCC296ACD51D01C94,0x055E2BAE5CC0C5C3,0x6270E2C21D6301B6,0x3B842720382219C0, + 0xD2F0900E846AB824,0x52FC6F277A1745D2,0xC6953C8CE94D8B0F,0xE009F8FE3095753E, + 0x655B2C7992284D0B,0x984A37D54347DFC4,0xEAB5AEBF8808E2A5,0x9A3FD2C090CC56BA, + 0x9CA0E0FFF84CD038,0x4C2595E4AFADE162,0xDF6708F4B3BC6302,0xBF620F237D54EBCA, + 0x93429D101C118260,0x097D4FD08CDDD4DA,0x8C2F9B572E60ECEF,0x708A7C7F18C4B41F, + 0x3A30DBA4DFE9D3FF,0x4006F19A7FB0F07B,0x5F6BF7DD4DC19EF4,0x1F6D064732716E8F, + 0xF9FBCC866A649D33,0x308C8DE567744464,0x8971B0F972A0292C,0xD61A47243F61B7D8, + 0xEFEB8511D4C82766,0x961CB6BE40D147A3,0xAAB35F25F7B812DE,0x76154E407044329D, + 0x513D76B64E570693,0xF3479AC7D2F90AA8,0x9B8B2E4477079C85,0x297EB99D3D85AC69 +},{ + 0x7E37E62DFC7D40C3,0x776F25A4EE939E5B,0xE045C850DD8FB5AD,0x86ED5BA711FF1952, + 0xE91D0BD9CF616B35,0x37E0AB256E408FFB,0x9607F6C031025A7A,0x0B02F5E116D23C9D, + 0xF3D8486BFB50650C,0x621CFF27C40875F5,0x7D40CB71FA5FD34A,0x6DAA6616DAA29062, + 0x9F5F354923EC84E2,0xEC847C3DC507C3B3,0x025A3668043CE205,0xA8BF9E6C4DAC0B19, + 0xFA808BE2E9BEBB94,0xB5B99C5277C74FA3,0x78D9BC95F0397BCC,0xE332E50CDBAD2624, + 0xC74FCE129332797E,0x1729ECEB2EA709AB,0xC2D6B9F69954D1F8,0x5D898CBFBAB8551A, + 0x859A76FB17DD8ADB,0x1BE85886362F7FB5,0xF6413F8FF136CD8A,0xD3110FA5BBB7E35C, + 0x0A2FEED514CC4D11,0xE83010EDCD7F1AB9,0xA1E75DE55F42D581,0xEEDE4A55C13B21B6, + 0xF2F5535FF94E1480,0x0CC1B46D1888761E,0xBCE15FDB6529913B,0x2D25E8975A7181C2, + 0x71817F1CE2D7A554,0x2E52C5CB5C53124B,0xF9F7A6BEEF9C281D,0x9E722E7D21F2F56E, + 0xCE170D9B81DCA7E6,0x0E9B82051CB4941B,0x1E712F623C49D733,0x21E45CFA42F9F7DC, + 0xCB8E7A7F8BBA0F60,0x8E98831A010FB646,0x474CCF0D8E895B23,0xA99285584FB27A95, + 0x8CC2B57205335443,0x42D5B8E984EFF3A5,0x012D1B34021E718C,0x57A6626AAE74180B, + 0xFF19FC06E3D81312,0x35BA9D4D6A7C6DFE,0xC9D44C178F86ED65,0x506523E6A02E5288, + 0x03772D5C06229389,0x8B01F4FE0B691EC0,0xF8DABD8AED825991,0x4C4E3AEC985B67BE, + 0xB10DF0827FBF96A9,0x6A69279AD4F8DAE1,0xE78689DCD3D5FF2E,0x812E1A2B1FA553D1, + 0xFBAD90D6EBA0CA18,0x1AC543B234310E39,0x1604F7DF2CB97827,0xA6241C6951189F02, + 0x753513CCEAAF7C5E,0x64F2A59FC84C4EFA,0x247D2B1E489F5F5A,0xDB64D718AB474C48, + 0x79F4A7A1F2270A40,0x1573DA832A9BEBAE,0x3497867968621C72,0x514838D2A2302304, + 0xF0AF6537FD72F685,0x1D06023E3A6B44BA,0x678588C3CE6EDD73,0x66A893F7CC70ACFF, + 0xD4D24E29B5EDA9DF,0x3856321470EA6A6C,0x07C3418C0E5A4A83,0x2BCBB22F5635BACD, + 0x04B46CD00878D90A,0x06EE5AB80C443B0F,0x3B211F4876C8F9E5,0x0958C38912EEDE98, + 0xD14B39CDBF8B0159,0x397B292072F41BE0,0x87C0409313E168DE,0xAD26E98847CAA39F, + 0x4E140C849C6785BB,0xD5FF551DB7F3D853,0xA0CA46D15D5CA40D,0xCD6020C787FE346F, + 0x84B76DCF15C3FB57,0xDEFDA0FCA121E4CE,0x4B8D7B6096012D3D,0x9AC642AD298A2C64, + 0x0875D8BD10F0AF14,0xB357C6EA7B8374AC,0x4D6321D89A451632,0xEDA96709C719B23F, + 0xF76C24BBF328BC06,0xC662D526912C08F2,0x3CE25EC47892B366,0xB978283F6F4F39BD, + 0xC08C8F9E9D6833FD,0x4F3917B09E79F437,0x593DE06FB2C08C10,0xD6887841B1D14BDA, + 0x19B26EEE32139DB0,0xB494876675D93E2F,0x825937771987C058,0x90E9AC783D466175, + 0xF1827E03FF6C8709,0x945DC0A8353EB87F,0x4516F9658AB5B926,0x3F9573987EB020EF, + 0xB855330B6D514831,0x2AE6A91B542BCB41,0x6331E413C6160479,0x408F8E8180D311A0, + 0xEFF35161C325503A,0xD06622F9BD9570D5,0x8876D9A20D4B8D49,0xA5533135573A0C8B, + 0xE168D364DF91C421,0xF41B09E7F50A2F8F,0x12B09B0F24C1A12D,0xDA49CC2CA9593DC4, + 0x1F5C34563E57A6BF,0x54D14F36A8568B82,0xAF7CDFE043F6419A,0xEA6A2685C943F8BC, + 0xE5DCBFB4D7E91D2B,0xB27ADDDE799D0520,0x6B443CAED6E6AB6D,0x7BAE91C9F61BE845, + 0x3EB868AC7CAE5163,0x11C7B65322E332A4,0xD23C1491B9A992D0,0x8FB5982E0311C7CA, + 0x70AC6428E0C9D4D8,0x895BC2960F55FCC5,0x76423E90EC8DEFD7,0x6FF0507EDE9E7267, + 0x3DCF45F07A8CC2EA,0x4AA06054941F5CB1,0x5810FB5BB0DEFD9C,0x5EFEA1E3BC9AC693, + 0x6EDD4B4ADC8003EB,0x741808F8E8B10DD2,0x145EC1B728859A22,0x28BC9F7350172944, + 0x270A06424EBDCCD3,0x972AEDF4331C2BF6,0x059977E40A66A886,0x2550302A4A812ED6, + 0xDD8A8DA0A7037747,0xC515F87A970E9B7B,0x3023EAA9601AC578,0xB7E3AA3A73FBADA6, + 0x0FB699311EAAE597,0x0000000000000000,0x310EF19D6204B4F4,0x229371A644DB6455, + 0x0DECAF591A960792,0x5CA4978BB8A62496,0x1C2B190A38753536,0x41A295B582CD602C, + 0x3279DCC16426277D,0xC1A194AA9F764271,0x139D803B26DFD0A1,0xAE51C4D441E83016, + 0xD813FA44AD65DFC1,0xAC0BF2BC45D4D213,0x23BE6A9246C515D9,0x49D74D08923DCF38, + 0x9D05032127D066E7,0x2F7FDEFF5E4D63C7,0xA47E2A0155247D07,0x99B16FF12FA8BFED, + 0x4661D4398C972AAF,0xDFD0BBC8A33F9542,0xDCA79694A51D06CB,0xB020EBB67DA1E725, + 0xBA0F0563696DAA34,0xE4F1A480D5F76CA7,0xC438E34E9510EAF7,0x939E81243B64F2FC, + 0x8DEFAE46072D25CF,0x2C08F3A3586FF04E,0xD7A56375B3CF3A56,0x20C947CE40E78650, + 0x43F8A3DD86F18229,0x568B795EAC6A6987,0x8003011F1DBB225D,0xF53612D3F7145E03, + 0x189F75DA300DEC3C,0x9570DB9C3720C9F3,0xBB221E576B73DBB8,0x72F65240E4F536DD, + 0x443BE25188ABC8AA,0xE21FFE38D9B357A8,0xFD43CA6EE7E4F117,0xCAA3614B89A47EEC, + 0xFE34E732E1C6629E,0x83742C431B99B1D4,0xCF3A16AF83C2D66A,0xAAE5A8044990E91C, + 0x26271D764CA3BD5F,0x91C4B74C3F5810F9,0x7C6DD045F841A2C6,0x7F1AFD19FE63314F, + 0xC8F957238D989CE9,0xA709075D5306EE8E,0x55FC5402AA48FA0E,0x48FA563C9023BEB4, + 0x65DFBEABCA523F76,0x6C877D22D8BCE1EE,0xCC4D3BF385E045E3,0xBEBB69B36115733E, + 0x10EAAD6720FD4328,0xB6CEB10E71E5DC2A,0xBDCC44EF6737E0B7,0x523F158EA412B08D, + 0x989C74C52DB6CE61,0x9BEB59992B945DE8,0x8A2CEFCA09776F4C,0xA3BD6B8D5B7E3784, + 0xEB473DB1CB5D8930,0xC3FBA2C29B4AA074,0x9C28181525CE176B,0x683311F2D0C438E4, + 0x5FD3BAD7BE84B71F,0xFC6ED15AE5FA809B,0x36CDB0116C5EFE77,0x29918447520958C8, + 0xA29070B959604608,0x53120EBAA60CC101,0x3A0C047C74D68869,0x691E0AC6D2DA4968, + 0x73DB4974E6EB4751,0x7A838AFDF40599C9,0x5A4ACD33B4E21F99,0x6046C94FC03497F0, + 0xE6AB92E8D1CB8EA2,0x3354C7F5663856F1,0xD93EE170AF7BAE4D,0x616BD27BC22AE67C, + 0x92B39A10397A8370,0xABC8B3304B8E9890,0xBF967287630B02B2,0x5B67D607B6FC6E15 +},{ + 0xD031C397CE553FE6,0x16BA5B01B006B525,0xA89BADE6296E70C8,0x6A1F525D77D3435B, + 0x6E103570573DFA0B,0x660EFB2A17FC95AB,0x76327A9E97634BF6,0x4BAD9D6462458BF5, + 0xF1830CAEDBC3F748,0xC5C8F542669131FF,0x95044A1CDC48B0CB,0x892962DF3CF8B866, + 0xB0B9E208E930C135,0xA14FB3F0611A767C,0x8D2605F21C160136,0xD6B71922FECC549E, + 0x37089438A5907D8B,0x0B5DA38E5803D49C,0x5A5BCC9CEA6F3CBC,0xEDAE246D3B73FFE5, + 0xD2B87E0FDE22EDCE,0x5E54ABB1CA8185EC,0x1DE7F88FE80561B9,0xAD5E1A870135A08C, + 0x2F2ADBD665CECC76,0x5780B5A782F58358,0x3EDC8A2EEDE47B3F,0xC9D95C3506BEE70F, + 0x83BE111D6C4E05EE,0xA603B90959367410,0x103C81B4809FDE5D,0x2C69B6027D0C774A, + 0x399080D7D5C87953,0x09D41E16487406B4,0xCDD63B1826505E5F,0xF99DC2F49B0298E8, + 0x9CD0540A943CB67F,0xBCA84B7F891F17C5,0x723D1DB3B78DF2A6,0x78AA6E71E73B4F2E, + 0x1433E699A071670D,0x84F21BE454620782,0x98DF3327B4D20F2F,0xF049DCE2D3769E5C, + 0xDB6C60199656EB7A,0x648746B2078B4783,0x32CD23598DCBADCF,0x1EA4955BF0C7DA85, + 0xE9A143401B9D46B5,0xFD92A5D9BBEC21B8,0xC8138C790E0B8E1B,0x2EE00B9A6D7BA562, + 0xF85712B893B7F1FC,0xEB28FED80BEA949D,0x564A65EB8A40EA4C,0x6C9988E8474A2823, + 0x4535898B121D8F2D,0xABD8C03231ACCBF4,0xBA2E91CAB9867CBD,0x7960BE3DEF8E263A, + 0x0C11A977602FD6F0,0xCB50E1AD16C93527,0xEAE22E94035FFD89,0x2866D12F5DE2CE1A, + 0xFF1B1841AB9BF390,0x9F9339DE8CFE0D43,0x964727C8C48A0BF7,0x524502C6AAAE531C, + 0x9B9C5EF3AC10B413,0x4FA2FA4942AB32A5,0x3F165A62E551122B,0xC74148DA76E6E3D7, + 0x924840E5E464B2A7,0xD372AE43D69784DA,0x233B72A105E11A86,0xA48A04914941A638, + 0xB4B68525C9DE7865,0xDDEABAACA6CF8002,0x0A9773C250B6BD88,0xC284FFBB5EBD3393, + 0x8BA0DF472C8F6A4E,0x2AEF6CB74D951C32,0x427983722A318D41,0x73F7CDFFBF389BB2, + 0x074C0AF9382C026C,0x8A6A0F0B243A035A,0x6FDAE53C5F88931F,0xC68B98967E538AC3, + 0x44FF59C71AA8E639,0xE2FCE0CE439E9229,0xA20CDE2479D8CD40,0x19E89FA2C8EBD8E9, + 0xF446BBCFF398270C,0x43B3533E2284E455,0xD82F0DCD8E945046,0x51066F12B26CE820, + 0xE73957AF6BC5426D,0x081ECE5A40C16FA0,0x3B193D4FC5BFAB7B,0x7FE66488DF174D42, + 0x0E9814EF705804D8,0x8137AC857C39D7C6,0xB1733244E185A821,0x695C3F896F11F867, + 0xF6CF0657E3EFF524,0x1AABF276D02963D5,0x2DA3664E75B91E5E,0x0289BD981077D228, + 0x90C1FD7DF413608F,0x3C5537B6FD93A917,0xAA12107E3919A2E0,0x0686DAB530996B78, + 0xDAA6B0559EE3826E,0xC34E2FF756085A87,0x6D5358A44FFF4137,0xFC587595B35948AC, + 0x7CA5095CC7D5F67E,0xFB147F6C8B754AC0,0xBFEB26AB91DDACF9,0x6896EFC567A49173, + 0xCA9A31E11E7C5C33,0xBBE44186B13315A9,0x0DDB793B689ABFE4,0x70B4A02BA7FA208E, + 0xE47A3A7B7307F951,0x8CECD5BE14A36822,0xEEED49B923B144D9,0x17708B4DB8B3DC31, + 0x6088219F2765FED3,0xB3FA8FDCF1F27A09,0x910B2D31FCA6099B,0x0F52C4A378ED6DCC, + 0x50CCBF5EBAD98134,0x6BD582117F662A4F,0x94CE9A50D4FDD9DF,0x2B25BCFB45207526, + 0x67C42B661F49FCBF,0x492420FC723259DD,0x03436DD418C2BB3C,0x1F6E4517F872B391, + 0xA08563BC69AF1F68,0xD43EA4BAEEBB86B6,0x01CAD04C08B56914,0xAC94CACB0980C998, + 0x54C3D8739A373864,0x26FEC5C02DBACAC2,0xDEA9D778BE0D3B3E,0x040F672D20EEB950, + 0xE5B0EA377BB29045,0xF30AB136CBB42560,0x62019C0737122CFB,0xE86B930C13282FA1, + 0xCC1CEB542EE5374B,0x538FD28AA21B3A08,0x1B61223AD89C0AC1,0x36C24474AD25149F, + 0x7A23D3E9F74C9D06,0xBE21F6E79968C5ED,0xCF5F868036278C77,0xF705D61BEB5A9C30, + 0x4D2B47D152DCE08D,0x5F9E7BFDC234ECF8,0x247778583DCD18EA,0x867BA67C4415D5AA, + 0x4CE1979D5A698999,0x0000000000000000,0xEC64F42133C696F1,0xB57C5569C16B1171, + 0xC1C7926F467F88AF,0x654D96FE0F3E2E97,0x15F936D5A8C40E19,0xB8A72C52A9F1AE95, + 0xA9517DAA21DB19DC,0x58D27104FA18EE94,0x5918A148F2AD8780,0x5CDD1629DAF657C4, + 0x8274C15164FB6CFA,0xD1FB13DBC6E056F2,0x7D6FD910CF609F6A,0xB63F38BDD9A9AA4D, + 0x3D9FE7FAF526C003,0x74BBC706871499DE,0xDF630734B6B8522A,0x3AD3ED03CD0AC26F, + 0xFADEAF2083C023D4,0xC00D42234ECAE1BB,0x8538CBA85CD76E96,0xC402250E6E2458EB, + 0x47BC3413026A5D05,0xAFD7A71F114272A4,0x978DF784CC3F62E3,0xB96DFC1EA144C781, + 0x21B2CF391596C8AE,0x318E4E8D950916F3,0xCE9556CC3E92E563,0x385A509BDD7D1047, + 0x358129A0B5E7AFA3,0xE6F387E363702B79,0xE0755D5653E94001,0x7BE903A5FFF9F412, + 0x12B53C2C90E80C75,0x3307F315857EC4DB,0x8FAFB86A0C61D31E,0xD9E5DD8186213952, + 0x77F8AAD29FD622E2,0x25BDA814357871FE,0x7571174A8FA1F0CA,0x137FEC60985D6561, + 0x30449EC19DBC7FE7,0xA540D4DD41F4CF2C,0xDC206AE0AE7AE916,0x5B911CD0E2DA55A8, + 0xB2305F90F947131D,0x344BF9ECBD52C6B7,0x5D17C665D2433ED0,0x18224FEEC05EB1FD, + 0x9E59E992844B6457,0x9A568EBFA4A5DD07,0xA3C60E68716DA454,0x7E2CB4C4D7A22456, + 0x87B176304CA0BCBE,0x413AEEA632F3367D,0x9915E36BBC67663B,0x40F03EEA3A465F69, + 0x1C2D28C3E0B008AD,0x4E682A054A1E5BB1,0x05C5B761285BD044,0xE1BF8D1A5B5C2915, + 0xF2C0617AC3014C74,0xB7F5E8F1D11CC359,0x63CB4C4B3FA745EF,0x9D1A84469C89DF6B, + 0xE33630824B2BFB3D,0xD5F474F6E60EEFA2,0xF58C6B83FB2D4E18,0x4676E45F0ADF3411, + 0x20781F751D23A1BA,0xBD629B3381AA7ED1,0xAE1D775319F71BB0,0xFED1C80DA32E9A84, + 0x5509083F92825170,0x29AC01635557A70E,0xA7C9694551831D04,0x8E65682604D4BA0A, + 0x11F651F8882AB749,0xD77DC96EF6793D8A,0xEF2799F52B042DCD,0x48EEF0B07A8730C9, + 0x22F1A2ED0D547392,0x6142F1D32FD097C7,0x4A674D286AF0E2E1,0x80FD7CC9748CBED2, + 0x717E7067AF4F499A,0x938290A9ECD1DBB3,0x88E3B293344DD172,0x2734158C250FA3D6 +}}; + +// Constant values for KeySchedule function +const unsigned char C[12][64] = {{ + 0xB1,0x08,0x5B,0xDA,0x1E,0xCA,0xDA,0xE9,0xEB,0xCB,0x2F,0x81,0xC0,0x65,0x7C,0x1F, + 0x2F,0x6A,0x76,0x43,0x2E,0x45,0xD0,0x16,0x71,0x4E,0xB8,0x8D,0x75,0x85,0xC4,0xFC, + 0x4B,0x7C,0xE0,0x91,0x92,0x67,0x69,0x01,0xA2,0x42,0x2A,0x08,0xA4,0x60,0xD3,0x15, + 0x05,0x76,0x74,0x36,0xCC,0x74,0x4D,0x23,0xDD,0x80,0x65,0x59,0xF2,0xA6,0x45,0x07 +},{ + 0x6F,0xA3,0xB5,0x8A,0xA9,0x9D,0x2F,0x1A,0x4F,0xE3,0x9D,0x46,0x0F,0x70,0xB5,0xD7, + 0xF3,0xFE,0xEA,0x72,0x0A,0x23,0x2B,0x98,0x61,0xD5,0x5E,0x0F,0x16,0xB5,0x01,0x31, + 0x9A,0xB5,0x17,0x6B,0x12,0xD6,0x99,0x58,0x5C,0xB5,0x61,0xC2,0xDB,0x0A,0xA7,0xCA, + 0x55,0xDD,0xA2,0x1B,0xD7,0xCB,0xCD,0x56,0xE6,0x79,0x04,0x70,0x21,0xB1,0x9B,0xB7 +},{ + 0xF5,0x74,0xDC,0xAC,0x2B,0xCE,0x2F,0xC7,0x0A,0x39,0xFC,0x28,0x6A,0x3D,0x84,0x35, + 0x06,0xF1,0x5E,0x5F,0x52,0x9C,0x1F,0x8B,0xF2,0xEA,0x75,0x14,0xB1,0x29,0x7B,0x7B, + 0xD3,0xE2,0x0F,0xE4,0x90,0x35,0x9E,0xB1,0xC1,0xC9,0x3A,0x37,0x60,0x62,0xDB,0x09, + 0xC2,0xB6,0xF4,0x43,0x86,0x7A,0xDB,0x31,0x99,0x1E,0x96,0xF5,0x0A,0xBA,0x0A,0xB2 +},{ + 0xEF,0x1F,0xDF,0xB3,0xE8,0x15,0x66,0xD2,0xF9,0x48,0xE1,0xA0,0x5D,0x71,0xE4,0xDD, + 0x48,0x8E,0x85,0x7E,0x33,0x5C,0x3C,0x7D,0x9D,0x72,0x1C,0xAD,0x68,0x5E,0x35,0x3F, + 0xA9,0xD7,0x2C,0x82,0xED,0x03,0xD6,0x75,0xD8,0xB7,0x13,0x33,0x93,0x52,0x03,0xBE, + 0x34,0x53,0xEA,0xA1,0x93,0xE8,0x37,0xF1,0x22,0x0C,0xBE,0xBC,0x84,0xE3,0xD1,0x2E +},{ + 0x4B,0xEA,0x6B,0xAC,0xAD,0x47,0x47,0x99,0x9A,0x3F,0x41,0x0C,0x6C,0xA9,0x23,0x63, + 0x7F,0x15,0x1C,0x1F,0x16,0x86,0x10,0x4A,0x35,0x9E,0x35,0xD7,0x80,0x0F,0xFF,0xBD, + 0xBF,0xCD,0x17,0x47,0x25,0x3A,0xF5,0xA3,0xDF,0xFF,0x00,0xB7,0x23,0x27,0x1A,0x16, + 0x7A,0x56,0xA2,0x7E,0xA9,0xEA,0x63,0xF5,0x60,0x17,0x58,0xFD,0x7C,0x6C,0xFE,0x57 +},{ + 0xAE,0x4F,0xAE,0xAE,0x1D,0x3A,0xD3,0xD9,0x6F,0xA4,0xC3,0x3B,0x7A,0x30,0x39,0xC0, + 0x2D,0x66,0xC4,0xF9,0x51,0x42,0xA4,0x6C,0x18,0x7F,0x9A,0xB4,0x9A,0xF0,0x8E,0xC6, + 0xCF,0xFA,0xA6,0xB7,0x1C,0x9A,0xB7,0xB4,0x0A,0xF2,0x1F,0x66,0xC2,0xBE,0xC6,0xB6, + 0xBF,0x71,0xC5,0x72,0x36,0x90,0x4F,0x35,0xFA,0x68,0x40,0x7A,0x46,0x64,0x7D,0x6E +},{ + 0xF4,0xC7,0x0E,0x16,0xEE,0xAA,0xC5,0xEC,0x51,0xAC,0x86,0xFE,0xBF,0x24,0x09,0x54, + 0x39,0x9E,0xC6,0xC7,0xE6,0xBF,0x87,0xC9,0xD3,0x47,0x3E,0x33,0x19,0x7A,0x93,0xC9, + 0x09,0x92,0xAB,0xC5,0x2D,0x82,0x2C,0x37,0x06,0x47,0x69,0x83,0x28,0x4A,0x05,0x04, + 0x35,0x17,0x45,0x4C,0xA2,0x3C,0x4A,0xF3,0x88,0x86,0x56,0x4D,0x3A,0x14,0xD4,0x93 +},{ + 0x9B,0x1F,0x5B,0x42,0x4D,0x93,0xC9,0xA7,0x03,0xE7,0xAA,0x02,0x0C,0x6E,0x41,0x41, + 0x4E,0xB7,0xF8,0x71,0x9C,0x36,0xDE,0x1E,0x89,0xB4,0x44,0x3B,0x4D,0xDB,0xC4,0x9A, + 0xF4,0x89,0x2B,0xCB,0x92,0x9B,0x06,0x90,0x69,0xD1,0x8D,0x2B,0xD1,0xA5,0xC4,0x2F, + 0x36,0xAC,0xC2,0x35,0x59,0x51,0xA8,0xD9,0xA4,0x7F,0x0D,0xD4,0xBF,0x02,0xE7,0x1E +},{ + 0x37,0x8F,0x5A,0x54,0x16,0x31,0x22,0x9B,0x94,0x4C,0x9A,0xD8,0xEC,0x16,0x5F,0xDE, + 0x3A,0x7D,0x3A,0x1B,0x25,0x89,0x42,0x24,0x3C,0xD9,0x55,0xB7,0xE0,0x0D,0x09,0x84, + 0x80,0x0A,0x44,0x0B,0xDB,0xB2,0xCE,0xB1,0x7B,0x2B,0x8A,0x9A,0xA6,0x07,0x9C,0x54, + 0x0E,0x38,0xDC,0x92,0xCB,0x1F,0x2A,0x60,0x72,0x61,0x44,0x51,0x83,0x23,0x5A,0xDB +},{ + 0xAB,0xBE,0xDE,0xA6,0x80,0x05,0x6F,0x52,0x38,0x2A,0xE5,0x48,0xB2,0xE4,0xF3,0xF3, + 0x89,0x41,0xE7,0x1C,0xFF,0x8A,0x78,0xDB,0x1F,0xFF,0xE1,0x8A,0x1B,0x33,0x61,0x03, + 0x9F,0xE7,0x67,0x02,0xAF,0x69,0x33,0x4B,0x7A,0x1E,0x6C,0x30,0x3B,0x76,0x52,0xF4, + 0x36,0x98,0xFA,0xD1,0x15,0x3B,0xB6,0xC3,0x74,0xB4,0xC7,0xFB,0x98,0x45,0x9C,0xED +},{ + 0x7B,0xCD,0x9E,0xD0,0xEF,0xC8,0x89,0xFB,0x30,0x02,0xC6,0xCD,0x63,0x5A,0xFE,0x94, + 0xD8,0xFA,0x6B,0xBB,0xEB,0xAB,0x07,0x61,0x20,0x01,0x80,0x21,0x14,0x84,0x66,0x79, + 0x8A,0x1D,0x71,0xEF,0xEA,0x48,0xB9,0xCA,0xEF,0xBA,0xCD,0x1D,0x7D,0x47,0x6E,0x98, + 0xDE,0xA2,0x59,0x4A,0xC0,0x6F,0xD8,0x5D,0x6B,0xCA,0xA4,0xCD,0x81,0xF3,0x2D,0x1B +},{ + 0x37,0x8E,0xE7,0x67,0xF1,0x16,0x31,0xBA,0xD2,0x13,0x80,0xB0,0x04,0x49,0xB1,0x7A, + 0xCD,0xA4,0x3C,0x32,0xBC,0xDF,0x1D,0x77,0xF8,0x20,0x12,0xD4,0x30,0x21,0x9F,0x9B, + 0x5D,0x80,0xEF,0x9D,0x18,0x91,0xCC,0x86,0xE7,0x1D,0xA4,0xAA,0x88,0xE1,0x28,0x52, + 0xFA,0xF4,0x17,0xD5,0xD9,0xB2,0x1B,0x99,0x48,0xBC,0x92,0x4A,0xF1,0x1B,0xD7,0x20 +}}; + + +static void AddModulo512(const void *a,const void *b,void *c) +{ + const unsigned char *A=a, *B=b; + unsigned char *C=c; + int t = 0; +#ifdef FULL_UNROLL +#define ADDBYTE_8(i) t = A[i] + B[i] + (t >> 8); C[i] = t & 0xFF; + + ADDBYTE_8(63) + ADDBYTE_8(62) + ADDBYTE_8(61) + ADDBYTE_8(60) + ADDBYTE_8(59) + ADDBYTE_8(58) + ADDBYTE_8(57) + ADDBYTE_8(56) + ADDBYTE_8(55) + ADDBYTE_8(54) + ADDBYTE_8(53) + ADDBYTE_8(52) + ADDBYTE_8(51) + ADDBYTE_8(50) + ADDBYTE_8(49) + ADDBYTE_8(48) + ADDBYTE_8(47) + ADDBYTE_8(46) + ADDBYTE_8(45) + ADDBYTE_8(44) + ADDBYTE_8(43) + ADDBYTE_8(42) + ADDBYTE_8(41) + ADDBYTE_8(40) + ADDBYTE_8(39) + ADDBYTE_8(38) + ADDBYTE_8(37) + ADDBYTE_8(36) + ADDBYTE_8(35) + ADDBYTE_8(34) + ADDBYTE_8(33) + ADDBYTE_8(32) + ADDBYTE_8(31) + ADDBYTE_8(30) + ADDBYTE_8(29) + ADDBYTE_8(28) + ADDBYTE_8(27) + ADDBYTE_8(26) + ADDBYTE_8(25) + ADDBYTE_8(24) + ADDBYTE_8(23) + ADDBYTE_8(22) + ADDBYTE_8(21) + ADDBYTE_8(20) + ADDBYTE_8(19) + ADDBYTE_8(18) + ADDBYTE_8(17) + ADDBYTE_8(16) + ADDBYTE_8(15) + ADDBYTE_8(14) + ADDBYTE_8(13) + ADDBYTE_8(12) + ADDBYTE_8(11) + ADDBYTE_8(10) + ADDBYTE_8(9) + ADDBYTE_8(8) + ADDBYTE_8(7) + ADDBYTE_8(6) + ADDBYTE_8(5) + ADDBYTE_8(4) + ADDBYTE_8(3) + ADDBYTE_8(2) + ADDBYTE_8(1) + ADDBYTE_8(0) + +#else + int i = 0; + + for(i=63;i>=0;i--) + { + t = A[i] + B[i] + (t >> 8); + C[i] = t & 0xFF; + } +#endif +} + +static void AddXor512(const void *a,const void *b,void *c) +{ + const unsigned long long *A=a, *B=b; + unsigned long long *C=c; +#ifdef FULL_UNROLL + C[0] = A[0] ^ B[0]; + C[1] = A[1] ^ B[1]; + C[2] = A[2] ^ B[2]; + C[3] = A[3] ^ B[3]; + C[4] = A[4] ^ B[4]; + C[5] = A[5] ^ B[5]; + C[6] = A[6] ^ B[6]; + C[7] = A[7] ^ B[7]; +#else + int i = 0; + + for(i=0; i<8; i++) { + C[i] = A[i] ^ B[i]; + } +#endif +} + +static void F(unsigned char *state) +{ + unsigned long long return_state[8]; + register unsigned long long r = 0; + r ^= TG[0][state[56]]; + r ^= TG[1][state[48]]; + r ^= TG[2][state[40]]; + r ^= TG[3][state[32]]; + r ^= TG[4][state[24]]; + r ^= TG[5][state[16]]; + r ^= TG[6][state[8]]; + r ^= TG[7][state[0]]; + return_state[0] = r; + r = 0; + + r ^= TG[0][state[57]]; + r ^= TG[1][state[49]]; + r ^= TG[2][state[41]]; + r ^= TG[3][state[33]]; + r ^= TG[4][state[25]]; + r ^= TG[5][state[17]]; + r ^= TG[6][state[9]]; + r ^= TG[7][state[1]]; + return_state[1] = r; + r = 0; + + r ^= TG[0][state[58]]; + r ^= TG[1][state[50]]; + r ^= TG[2][state[42]]; + r ^= TG[3][state[34]]; + r ^= TG[4][state[26]]; + r ^= TG[5][state[18]]; + r ^= TG[6][state[10]]; + r ^= TG[7][state[2]]; + return_state[2] = r; + r = 0; + + r ^= TG[0][state[59]]; + r ^= TG[1][state[51]]; + r ^= TG[2][state[43]]; + r ^= TG[3][state[35]]; + r ^= TG[4][state[27]]; + r ^= TG[5][state[19]]; + r ^= TG[6][state[11]]; + r ^= TG[7][state[3]]; + return_state[3] = r; + r = 0; + + r ^= TG[0][state[60]]; + r ^= TG[1][state[52]]; + r ^= TG[2][state[44]]; + r ^= TG[3][state[36]]; + r ^= TG[4][state[28]]; + r ^= TG[5][state[20]]; + r ^= TG[6][state[12]]; + r ^= TG[7][state[4]]; + return_state[4] = r; + r = 0; + + r ^= TG[0][state[61]]; + r ^= TG[1][state[53]]; + r ^= TG[2][state[45]]; + r ^= TG[3][state[37]]; + r ^= TG[4][state[29]]; + r ^= TG[5][state[21]]; + r ^= TG[6][state[13]]; + r ^= TG[7][state[5]]; + return_state[5] = r; + r = 0; + + r ^= TG[0][state[62]]; + r ^= TG[1][state[54]]; + r ^= TG[2][state[46]]; + r ^= TG[3][state[38]]; + r ^= TG[4][state[30]]; + r ^= TG[5][state[22]]; + r ^= TG[6][state[14]]; + r ^= TG[7][state[6]]; + return_state[6] = r; + r = 0; + + r ^= TG[0][state[63]]; + r ^= TG[1][state[55]]; + r ^= TG[2][state[47]]; + r ^= TG[3][state[39]]; + r ^= TG[4][state[31]]; + r ^= TG[5][state[23]]; + r ^= TG[6][state[15]]; + r ^= TG[7][state[7]]; + return_state[7] = r; + + memcpy(state,(unsigned char*)return_state,64); +} + +#define KeySchedule(K,i) AddXor512(K,C[i],K); F(K); + +static void E(unsigned char *K,const unsigned char *m, unsigned char *state) +{ +#ifdef FULL_UNROLL + AddXor512(m,K,state); + + F(state); + KeySchedule(K,0); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,1); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,2); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,3); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,4); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,5); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,6); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,7); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,8); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,9); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,10); + AddXor512(state,K,state); + + F(state); + KeySchedule(K,11); + AddXor512(state,K,state); +#else + int i = 0; + + AddXor512(m,K,state); + + for(i=0;i<12;i++) { + F(state); + KeySchedule(K,i); + AddXor512(state,K,state); + } +#endif +} + +static void g_N(const unsigned char *N,unsigned char *h,const unsigned char *m) +{ + unsigned char t[64], K[64]; + + AddXor512(N,h,K); + + F(K); + + E(K,m,t); + + AddXor512(t,h,t); + AddXor512(t,m,h); +} + +static void hash_X(unsigned char *IV,const unsigned char *message,unsigned long long length,unsigned char *out) +{ + unsigned char v512[64] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00 + }; + unsigned char v0[64] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + unsigned char Sigma[64] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + unsigned char N[64] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + unsigned char m[64], *hash = IV; + unsigned long long len = length; + + // Stage 2 + while (len >= 512) + { + memcpy(m, message + len/8 - 63 - ( (len & 0x7) == 0 ), 64); + + g_N(N,hash,m); + AddModulo512(N,v512,N); + AddModulo512(Sigma,m,Sigma); + len -= 512; + } + + memset(m,0,64); + memcpy(m + 63 - len/8 + ( (len & 0x7) == 0 ), message, len/8 + 1 - ( (len & 0x7) == 0 )); + + // Stage 3 + m[ 63 - len/8 ] |= (1 << (len & 0x7)); + + g_N(N,hash,m); + v512[63] = len & 0xFF; + v512[62] = (unsigned char) (len >> 8); + AddModulo512(N,v512,N); + + AddModulo512(Sigma,m,Sigma); + + g_N(v0,hash,N); + g_N(v0,hash,Sigma); + + memcpy(out, hash, 64); +} + +static void hash_512(const unsigned char *message, unsigned long long length, unsigned char *out) +{ + unsigned char IV[64] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + }; + + hash_X(IV,message,length,out); +} + +static void hash_256(const unsigned char *message, unsigned long long length, unsigned char *out) +{ + unsigned char IV[64] = { + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, + 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 + }; + unsigned char hash[64]; + + hash_X(IV,message,length,hash); + + memcpy(out,hash,32); +} + + + + + +/* see sph_gost.h */ +void +sph_gost256_init(void *cc) +{ + //gost_init(cc, 256); +} + +/* see sph_gost.h */ +void +sph_gost256(void *cc, const void *data, size_t len) +{ + hash_256(data, 8*len, cc); +} + +/* see sph_gost.h */ +void +sph_gost256_close(void *cc, void *dst) +{ + //sph_gost256_addbits_and_close(cc, 0, 0, dst); + memcpy(dst, cc, 32); +} + +/* see sph_gost.h */ +void +sph_gost256_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + //gost_close32(cc, ub, n, dst); +} + +/* see sph_gost.h */ +void +sph_gost512_init(void *cc) +{ + //gost_init(cc, 512); +} + +/* see sph_gost.h */ +void +sph_gost512(void *cc, const void *data, size_t len) +{ + hash_512(data, 8*len, cc); +} + +/* see sph_gost.h */ +void +sph_gost512_close(void *cc, void *dst) +{ + //sph_gost512_addbits_and_close(cc, 0, 0, dst); + memcpy(dst, cc, 64); +} + +/* see sph_gost.h */ +void +sph_gost512_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) +{ + //gost_close64(cc, ub, n, dst); +} + + +#ifdef __cplusplus +} +#endif diff --git a/stratum/stratum.cpp b/stratum/stratum.cpp index 02054e43c..d8d443649 100644 --- a/stratum/stratum.cpp +++ b/stratum/stratum.cpp @@ -116,6 +116,7 @@ YAAMP_ALGO g_algos[] = {"neoscrypt", neoscrypt_hash, 0x10000, 0, 0}, {"c11", c11_hash, 1, 0, 0}, + {"dedal", dedal_hash, 0x100, 0, 0}, {"x11", x11_hash, 1, 0, 0}, {"x12", x12_hash, 1, 0, 0}, {"x13", x13_hash, 1, 0, 0}, @@ -123,6 +124,7 @@ YAAMP_ALGO g_algos[] = {"x15", x15_hash, 1, 0, 0}, {"x17", x17_hash, 1, 0, 0}, {"x22i", x22i_hash, 1, 0, 0}, + {"x20r", x20r_hash, 0x100, 0, 0}, {"x21s", x21s_hash, 0x100, 0, 0}, {"x11evo", x11evo_hash, 1, 0, 0}, @@ -146,6 +148,7 @@ YAAMP_ALGO g_algos[] = {"bastion", bastion_hash, 1, 0 }, {"blake", blake_hash, 1, 0 }, {"blakecoin", blakecoin_hash, 1 /*0x100*/, 0, sha256_hash_hex }, + {"blake2b", blake2b_hash, 1, 0 }, {"blake2s", blake2s_hash, 1, 0 }, {"vanilla", blakecoin_hash, 1, 0 }, {"decred", decred_hash, 1, 0 }, @@ -194,6 +197,7 @@ YAAMP_ALGO g_algos[] = {"aergo", aergo_hash, 1, 0, 0}, {"sha256t", sha256t_hash, 1, 0, 0}, // sha256 3x + {"sha256q", sha256q_hash, 1, 0, 0}, // sha256 4x {"sib", sib_hash, 1, 0, 0}, diff --git a/stratum/stratum.h b/stratum/stratum.h index 92356fba9..5f04cd373 100644 --- a/stratum/stratum.h +++ b/stratum/stratum.h @@ -149,6 +149,7 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/a5a.h" #include "algos/c11.h" +#include "algos/dedal.h" #include "algos/x11.h" #include "algos/x11evo.h" #include "algos/x12.h" @@ -156,6 +157,7 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/x14.h" #include "algos/x15.h" #include "algos/x16r.h" +#include "algos/x20r.h" #include "algos/x16s.h" #include "algos/x17.h" #include "algos/x22i.h" @@ -173,6 +175,7 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/lyra2z.h" #include "algos/blake.h" #include "algos/blakecoin.h" +#include "algos/blake2b.h" #include "algos/blake2s.h" #include "algos/qubit.h" #include "algos/groestl.h" @@ -180,6 +183,7 @@ void sha256_double_hash_hex(const char *input, char *output, unsigned int len); #include "algos/skein.h" #include "algos/keccak.h" #include "algos/sha256t.h" +#include "algos/sha256q.h" #include "algos/skunk.h" #include "algos/timetravel.h" #include "algos/bitcore.h" diff --git a/web/yaamp/core/functions/yaamp.php b/web/yaamp/core/functions/yaamp.php index 98913e44e..2cc413006 100755 --- a/web/yaamp/core/functions/yaamp.php +++ b/web/yaamp/core/functions/yaamp.php @@ -6,6 +6,7 @@ function yaamp_get_algos() return array( 'sha256', 'sha256t', + 'sha256q', 'scrypt', 'scryptn', 'allium', @@ -17,7 +18,9 @@ function yaamp_get_algos() 'blake', 'blakecoin', 'blake2s', + 'blake2b', 'decred', + 'dedal', 'deep', 'exosis', 'hmq1725', @@ -50,6 +53,7 @@ function yaamp_get_algos() 'x16s', 'x17', 'x22i', + 'x20r', 'x21s', 'xevan', 'groestl', // dmd-gr -m 256 (deprecated) @@ -84,10 +88,13 @@ function yaamp_algo_mBTC_factor($algo) switch($algo) { case 'sha256': case 'sha256t': + case 'sha256q': case 'blake': case 'blakecoin': case 'blake2s': + case 'blake2b': case 'decred': + case 'dedal': case 'keccak': case 'keccakc': case 'lbry': @@ -143,11 +150,13 @@ function getAlgoColors($algo) $a = array( 'sha256' => '#d0d0a0', 'sha256t' => '#d0d0f0', + 'sha256q' => '#9696dd', 'scrypt' => '#c0c0e0', 'neoscrypt' => '#a0d0f0', 'scryptn' => '#d0d0d0', 'c11' => '#a0a0d0', 'decred' => '#f0f0f0', + 'dedal' => '#g0f0f0', 'deep' => '#e0ffff', 'x11' => '#f0f0a0', 'x11evo' => '#c0f0c0', @@ -159,6 +168,7 @@ function getAlgoColors($algo) 'x16s' => '#f0b080', 'x17' => '#f0b0a0', 'x22i' => '#f0a090', + 'x20r' => '#c0a090', 'x21s' => '#f0a090', 'xevan' => '#f0b0a0', 'allium' => '#80a0d0', @@ -168,6 +178,7 @@ function getAlgoColors($algo) 'bastion' => '#e0b0b0', 'blake' => '#f0f0f0', 'blakecoin' => '#f0f0f0', + 'blake2b' => '#f2c81f', 'exosis' => '#49CCFE', 'groestl' => '#d0a0a0', 'jha' => '#a0d0c0', @@ -225,6 +236,7 @@ function getAlgoPort($algo) $a = array( 'sha256' => 3333, 'sha256t' => 3339, + 'sha256q' => 3337, 'lbry' => 3334, 'scrypt' => 3433, 'timetravel' => 3555, @@ -241,6 +253,7 @@ function getAlgoPort($algo) 'x16s' => 3663, 'x17' => 3737, 'x22i' => 3223, + 'x20r' => 3352, 'x21s' => 3224, 'aergo' => 3691, 'xevan' => 3739, @@ -275,8 +288,10 @@ function getAlgoPort($algo) 'blake' => 5733, 'blakecoin' => 5743, 'decred' => 3252, + 'dedal' => 3353, 'vanilla' => 5755, 'blake2s' => 5766, + 'blake2b' => 5777, 'penta' => 5833, 'rainforest' => 7443, 'luffa' => 5933,