From 6b3f9fef735f799a66f28dc5e52bfbb0ca2d77e8 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Mon, 24 Nov 2014 19:35:32 +0100 Subject: [PATCH] Added KeccakHash (aka SHA-3) class + make sure that "public" functions and classes are actually exported from the DLL. --- MUtilities_VS2013.vcxproj | 21 +- MUtilities_VS2013.vcxproj.filters | 6 + include/MUtils/Global.h | 32 +- include/MUtils/KeccakHash.h | 113 ++ include/MUtils/OSSupport.h | 12 +- include/MUtils/UpdateChecker.h | 8 +- include/MUtils/Version.h | 182 +-- src/3rd_party/keccak_impl.h | 2001 +++++++++++++++++++++++++++++ src/KeccakHash.cpp | 210 +++ src/Version.cpp | 50 +- 10 files changed, 2511 insertions(+), 124 deletions(-) create mode 100644 include/MUtils/KeccakHash.h create mode 100644 src/3rd_party/keccak_impl.h create mode 100644 src/KeccakHash.cpp diff --git a/MUtilities_VS2013.vcxproj b/MUtilities_VS2013.vcxproj index 5cd4d5a..130c12a 100644 --- a/MUtilities_VS2013.vcxproj +++ b/MUtilities_VS2013.vcxproj @@ -16,6 +16,7 @@ + @@ -24,6 +25,7 @@ + "$(QTDIR)\bin\moc.exe" -o "$(SolutionDir)tmp\$(ProjectName)\MOC_%(Filename).cpp" "%(FullPath)" @@ -43,6 +45,7 @@ {55405FE1-149F-434C-9D72-4B64348D2A08} Win32Proj MUtilities + MUtilities @@ -80,18 +83,18 @@ $(SolutionDir)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\obj\$(Platform)\$(Configuration)\ - libMUtils32-1 + $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\ + MUtils32-1 $(SolutionDir)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\obj\$(Platform)\$(Configuration)\ - libMUtils32-1 + $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\ + MUtils32-1 $(SolutionDir)\bin\$(Platform)\$(Configuration)\ - $(SolutionDir)\obj\$(Platform)\$(Configuration)\ - libMUtils32-1 + $(SolutionDir)\obj\$(Platform)\$(Configuration)\$(ProjectName)\ + MUtils32-1 @@ -99,7 +102,7 @@ Level3 Disabled - WIN32;_DEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_DEBUG;%(PreprocessorDefinitions) + WIN32;MUTILS_DLL_EXPORT;_DEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebugDLL NoExtensions $(ProjectDir)\include;$(QTDIR)\include;$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;%(AdditionalIncludeDirectories) @@ -119,7 +122,7 @@ Full true true - WIN32;NDEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_NO_DEBUG;%(PreprocessorDefinitions) + WIN32;MUTILS_DLL_EXPORT;NDEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_DLL;QT_NO_DEBUG;%(PreprocessorDefinitions) MultiThreadedDLL NoExtensions AnySuitable @@ -147,7 +150,7 @@ Full true true - WIN32;NDEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_NODLL;QT_NO_DEBUG;%(PreprocessorDefinitions) + WIN32;MUTILS_DLL_EXPORT;NDEBUG;_LIB;QT_GUI_LIB;QT_CORE_LIB;QT_THREAD_SUPPORT;QT_NODLL;QT_NO_DEBUG;%(PreprocessorDefinitions) MultiThreaded NoExtensions AnySuitable diff --git a/MUtilities_VS2013.vcxproj.filters b/MUtilities_VS2013.vcxproj.filters index fea27eb..bde2a89 100644 --- a/MUtilities_VS2013.vcxproj.filters +++ b/MUtilities_VS2013.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + @@ -53,6 +56,9 @@ Public Headers + + Public Headers + diff --git a/include/MUtils/Global.h b/include/MUtils/Global.h index 4b41eee..07a33f2 100644 --- a/include/MUtils/Global.h +++ b/include/MUtils/Global.h @@ -28,22 +28,40 @@ class QProcess; /////////////////////////////////////////////////////////////////////////////// +//MUtils API +#ifdef _MSC_VER +# ifdef MUTILS_DLL_EXPORT +# define MUTILS_API __declspec(dllexport) +# else +# define MUTILS_API __declspec(dllimport) +# endif +#else +# define MUTILS_API +#endif + +//Helper Macros +#define MUTILS_MAKE_STRING_HELPER(X) #X +#define MUTILS_MAKE_STRING(X) MUTILS_MAKE_STRING_HELPER(X) +#define MUTILS_COMPILER_WARNING(TXT) __pragma(message(__FILE__ "(" MUTILS_MAKE_STRING(__LINE__) ") : warning: " TXT)) + +/////////////////////////////////////////////////////////////////////////////// + namespace MUtils { //Temp Folder - const QString &temp_folder(void); + MUTILS_API const QString& temp_folder(void); //Process Utils - void init_process(QProcess &process, const QString &wokringDir, const bool bReplaceTempDir = true); + MUTILS_API void init_process(QProcess &process, const QString &wokringDir, const bool bReplaceTempDir = true); //Random - void seed_rand(void); - QString rand_str(const bool &bLong = false); - quint32 next_rand32(void); - quint64 next_rand64(void); + MUTILS_API void seed_rand(void); + MUTILS_API QString rand_str(const bool &bLong = false); + MUTILS_API quint32 next_rand32(void); + MUTILS_API quint64 next_rand64(void); //Version - const char* buildDate(void); + MUTILS_API const char* buildDate(void); } /////////////////////////////////////////////////////////////////////////////// diff --git a/include/MUtils/KeccakHash.h b/include/MUtils/KeccakHash.h new file mode 100644 index 0000000..d634a01 --- /dev/null +++ b/include/MUtils/KeccakHash.h @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +/*************************************************************************** +** ** +** QKeccakHash, an API wrapper bringing the optimized implementation of ** +** Keccak (http://keccak.noekeon.org/) to Qt. ** +** Copyright (C) 2013 Emanuel Eichhammer ** +** ** +** This program is free software: you can redistribute it and/or modify ** +** it under the terms of the GNU General Public License as published by ** +** the Free Software Foundation, either version 3 of the License, or ** +** (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, ** +** but WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program. If not, see http://www.gnu.org/licenses/. ** +** ** +**************************************************************************** +** Author: Emanuel Eichhammer ** +** Website/Contact: http://www.WorksLikeClockwork.com/ ** +** Date: 12.01.12 ** +****************************************************************************/ + +#pragma once + +//MUtils +#include + +//Qt +#include +#include +#include + +namespace MUtils +{ + // Section from KeccakSponge.h + // needed here, since hashState needs to be explicitly 32-byte aligned and therefore can't be + // transformed into a class (in order to forward declarate) like in the other hash wrappers. + namespace KeccakImpl + { + #define KeccakPermutationSize 1600 + #define KeccakPermutationSizeInBytes (KeccakPermutationSize/8) + #define KeccakMaximumRate 1536 + #define KeccakMaximumRateInBytes (KeccakMaximumRate/8) + + #if defined(__GNUC__) + #define ALIGN __attribute__ ((aligned(32))) + #elif defined(_MSC_VER) + #define ALIGN __declspec(align(32)) + #else + #define ALIGN + #endif + + ALIGN typedef struct spongeStateStruct + { + ALIGN unsigned char state[KeccakPermutationSizeInBytes]; + ALIGN unsigned char dataQueue[KeccakMaximumRateInBytes]; + unsigned int rate; + unsigned int capacity; + unsigned int bitsInQueue; + unsigned int fixedOutputLength; + int squeezing; + unsigned int bitsAvailableForSqueezing; + } + spongeState; + typedef spongeState hashState; + } + // End Section from KeccakSponge.h + + class MUTILS_API KeccakHash + { + public: + enum HashBits {hb224, hb256, hb384, hb512}; + + KeccakHash(); + ~KeccakHash(); + + static bool selfTest(void); + + bool init(HashBits hashBits=hb256); + bool addData(const QByteArray &data); + bool addData(const char *data, int size); + const QByteArray &finalize(); + + protected: + bool m_initialized; + KeccakImpl::hashState *m_state; + QByteArray m_hashResult; + }; +}; diff --git a/include/MUtils/OSSupport.h b/include/MUtils/OSSupport.h index ac7a0a5..0d8ed5e 100644 --- a/include/MUtils/OSSupport.h +++ b/include/MUtils/OSSupport.h @@ -21,6 +21,10 @@ #pragma once +//MUtils +#include + +//Qt #include #include @@ -50,16 +54,16 @@ namespace MUtils network_type_t; //Get known Folder - const QString &known_folder(known_folder_t folder_id); + MUTILS_API const QString &known_folder(known_folder_t folder_id); //Current Date - QDate current_date(void); + MUTILS_API QDate current_date(void); //Network Status - int network_status(void); + MUTILS_API int network_status(void); //Error handling - void fatal_exit(const char* const errorMessage); + MUTILS_API void fatal_exit(const char* const errorMessage); } } diff --git a/include/MUtils/UpdateChecker.h b/include/MUtils/UpdateChecker.h index 9b582aa..4ad9f00 100644 --- a/include/MUtils/UpdateChecker.h +++ b/include/MUtils/UpdateChecker.h @@ -21,6 +21,10 @@ #pragma once +//MUtils +#include + +//Qt #include #include @@ -28,7 +32,7 @@ namespace MUtils { - class UpdateCheckerInfo + class MUTILS_API UpdateCheckerInfo { friend class UpdateChecker; @@ -54,7 +58,7 @@ namespace MUtils // ---------------------------------------------------------------- - class UpdateChecker : public QThread + class MUTILS_API UpdateChecker : public QThread { Q_OBJECT diff --git a/include/MUtils/Version.h b/include/MUtils/Version.h index 86e149b..dfae3e9 100644 --- a/include/MUtils/Version.h +++ b/include/MUtils/Version.h @@ -21,106 +21,126 @@ #pragma once +//MUtils +#include + +//Qt #include #include - -/////////////////////////////////////////////////////////////////////////////// - -#define MUTILS_MAKE_STRING_HELPER(X) #X -#define MUTILS_MAKE_STRING(X) MUTILS_MAKE_STRING_HELPER(X) -#define MUTILS_COMPILER_WARNING(TXT) __pragma(message(__FILE__ "(" MUTILS_MAKE_STRING(__LINE__) ") : warning: " TXT)) +#include namespace MUtils { - namespace Version + class MUTILS_API Version { - //Raw Build date - const char *const BUILD_DATE = __DATE__; + public: + //Get Build Date + static const QDate build_date(const char *const date_str = build_date_raw()); - //Get Build Data - const QDate build_date(const char *const raw_date = BUILD_DATE); + //Get Build Time + static const QTime build_time(const char *const time_str = build_time_raw()); //Compiler detection - #if defined(__INTEL_COMPILER) - #if (__INTEL_COMPILER >= 1500) - static const char *COMPILER_VERS = "ICL 15." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); - #elif (__INTEL_COMPILER >= 1400) - static const char *COMPILER_VERS = "ICL 14." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); - #elif (__INTEL_COMPILER >= 1300) - static const char *COMPILER_VERS = "ICL 13." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); - #elif (__INTEL_COMPILER >= 1200) - static const char *COMPILER_VERS = "ICL 12." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); - #elif (__INTEL_COMPILER >= 1100) - static const char *COMPILER_VERS = "ICL 11.x"; - #elif (__INTEL_COMPILER >= 1000) - static const char *COMPILER_VERS = "ICL 10.x"; - #else - #error Compiler is not supported! - #endif - #elif defined(_MSC_VER) - #if (_MSC_VER == 1800) - #if (_MSC_FULL_VER == 180021005) - static const char *COMPILER_VERS = "MSVC 2013"; - #elif (_MSC_FULL_VER == 180030501) - static const char *COMPILER_VERS = "MSVC 2013.2"; - #elif (_MSC_FULL_VER == 180030723) - static const char *COMPILER_VERS = "MSVC 2013.3"; - #elif (_MSC_FULL_VER == 180031101) - static const char *COMPILER_VERS = "MSVC 2013.4"; + static const char *const compiler_version(void) + { + #if defined(__INTEL_COMPILER) + #if (__INTEL_COMPILER >= 1500) + static const char *const COMPILER_VERS = "ICL 15." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); + #elif (__INTEL_COMPILER >= 1400) + static const char *const COMPILER_VERS = "ICL 14." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); + #elif (__INTEL_COMPILER >= 1300) + static const char *const COMPILER_VERS = "ICL 13." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); + #elif (__INTEL_COMPILER >= 1200) + static const char *const COMPILER_VERS = "ICL 12." MUTILS_MAKE_STRING(__INTEL_COMPILER_BUILD_DATE); + #elif (__INTEL_COMPILER >= 1100) + static const char *const COMPILER_VERS = "ICL 11.x"; + #elif (__INTEL_COMPILER >= 1000) + static const char *const COMPILER_VERS = "ICL 10.x"; #else - #error Compiler version is not supported yet! + #error Compiler is not supported! #endif - #elif (_MSC_VER == 1700) - #if (_MSC_FULL_VER == 170050727) - static const char *COMPILER_VERS = "MSVC 2012"; - #elif (_MSC_FULL_VER == 170051106) - static const char *COMPILER_VERS = "MSVC 2012.1"; - #elif (_MSC_FULL_VER == 170060315) - static const char *COMPILER_VERS = "MSVC 2012.2"; - #elif (_MSC_FULL_VER == 170060610) - static const char *COMPILER_VERS = "MSVC 2012.3"; - #elif (_MSC_FULL_VER == 170061030) - static const char *COMPILER_VERS = "MSVC 2012.4"; + #elif defined(_MSC_VER) + #if (_MSC_VER == 1800) + #if (_MSC_FULL_VER == 180021005) + static const char *const COMPILER_VERS = "MSVC 2013"; + #elif (_MSC_FULL_VER == 180030501) + static const char *const COMPILER_VERS = "MSVC 2013.2"; + #elif (_MSC_FULL_VER == 180030723) + static const char *const COMPILER_VERS = "MSVC 2013.3"; + #elif (_MSC_FULL_VER == 180031101) + static const char *const COMPILER_VERS = "MSVC 2013.4"; + #else + #error Compiler version is not supported yet! + #endif + #elif (_MSC_VER == 1700) + #if (_MSC_FULL_VER == 170050727) + static const char *const COMPILER_VERS = "MSVC 2012"; + #elif (_MSC_FULL_VER == 170051106) + static const char *const COMPILER_VERS = "MSVC 2012.1"; + #elif (_MSC_FULL_VER == 170060315) + static const char *const COMPILER_VERS = "MSVC 2012.2"; + #elif (_MSC_FULL_VER == 170060610) + static const char *const COMPILER_VERS = "MSVC 2012.3"; + #elif (_MSC_FULL_VER == 170061030) + static const char *const COMPILER_VERS = "MSVC 2012.4"; + #else + #error Compiler version is not supported yet! + #endif + #elif (_MSC_VER == 1600) + #if (_MSC_FULL_VER >= 160040219) + static const char *const COMPILER_VERS = "MSVC 2010-SP1"; + #else + static const char *const COMPILER_VERS = "MSVC 2010"; + #endif + #elif (_MSC_VER == 1500) + #if (_MSC_FULL_VER >= 150030729) + static const char *const COMPILER_VERS = "MSVC 2008-SP1"; + #else + static const char *const COMPILER_VERS = "MSVC 2008"; + #endif #else - #error Compiler version is not supported yet! - #endif - #elif (_MSC_VER == 1600) - #if (_MSC_FULL_VER >= 160040219) - static const char *COMPILER_VERS = "MSVC 2010-SP1"; - #else - static const char *COMPILER_VERS = "MSVC 2010"; - #endif - #elif (_MSC_VER == 1500) - #if (_MSC_FULL_VER >= 150030729) - static const char *COMPILER_VERS = "MSVC 2008-SP1"; - #else - static const char *COMPILER_VERS = "MSVC 2008"; + #error Compiler is not supported! #endif #else #error Compiler is not supported! #endif - // Note: /arch:SSE and /arch:SSE2 are only available for the x86 platform - #if !defined(_M_X64) && defined(_M_IX86_FP) - #if (_M_IX86_FP == 1) - MUTILS_COMPILER_WARNING("SSE instruction set is enabled!") - #elif (_M_IX86_FP == 2) - MUTILS_COMPILER_WARNING("SSE2 (or higher) instruction set is enabled!") - #endif - #endif - #else - #error Compiler is not supported! - #endif + return COMPILER_VERS; + } //Architecture detection - #if defined(_M_X64) - static const char *COMPILER_ARCH = "x64"; - #elif defined(_M_IX86) - static const char *COMPILER_ARCH = "x86"; - #else - #error Architecture is not supported! - #endif - } + static const char *const compiler_arch(void) + { + #if defined(_M_X64) + static const char *const COMPILER_ARCH = "x64"; + #elif defined(_M_IX86) + static const char *const COMPILER_ARCH = "x86"; + #else + #error Architecture is not supported! + #endif + + return COMPILER_ARCH; + } + + private: + //Raw Build date + static const char *const build_date_raw(void) + { + static const char *const RAW_BUILD_DATE = __DATE__; + return RAW_BUILD_DATE; + } + + //Raw Build date + static const char *const build_time_raw(void) + { + static const char *const RAW_BUILD_TIME = __TIME__; + return RAW_BUILD_TIME; + } + + //Disable construction + Version(void) { throw 666; } + Version(const Version&) { throw 666; } + }; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/3rd_party/keccak_impl.h b/src/3rd_party/keccak_impl.h new file mode 100644 index 0000000..7155ede --- /dev/null +++ b/src/3rd_party/keccak_impl.h @@ -0,0 +1,2001 @@ +/*************************************************************************** +** ** +** Keccak (http://keccak.noekeon.org/) implementation file ** +** ** +** This file implements the Keccak hash algorithm as provided by the ** +** inventors, and submitted to the third round of the NIST SHA-3 ** +** competition. ** +** For the QKeccakHash wrapper, the originally multiple files were ** +** combined in this one. Slight modifications have been made to ** +** allow use in C++ as an independently included .cpp file. ** +** It is not meant to be compiled into an object, hence, there is no ** +** header. ** +** ** +** The code here is not part of the actual QKeccakHash implementation ** +** and thus not licensed under the GPLv3 but under its respecitve ** +** license given by the inventors. Typically, this means it is in the ** +** public domain, if not noted otherwise. ** +** ** +***************************************************************************/ + +namespace MUtils { +namespace KeccakImpl { + +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; +typedef unsigned long long int UINT64; + +// ================================================================================ +// =================== brg_endian.h +// ================================================================================ + + +/* + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + Issue Date: 20/12/2007 + Changes for ARM 9/9/2010 +*/ + +#ifndef _BRG_ENDIAN_H +#define _BRG_ENDIAN_H + +#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ +#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ + +#if 0 +/* Include files where endian defines and byteswap functions may reside */ +#if defined( __sun ) +# include +#elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) +# include +#elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ + defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) +# include +#elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) +# if !defined( __MINGW32__ ) && !defined( _AIX ) +# include +# if !defined( __BEOS__ ) +# include +# endif +# endif +#endif +#endif + +/* Now attempt to set the define for platform byte order using any */ +/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ +/* seem to encompass most endian symbol definitions */ + +#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) +# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) +# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( _BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( _LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) +# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) +# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif defined( __BIG_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#elif defined( __LITTLE_ENDIAN__ ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#endif + +/* if the platform byte order could not be determined, then try to */ +/* set this define using common machine defines */ +#if !defined(PLATFORM_BYTE_ORDER) + +#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ + defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ + defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ + defined( vax ) || defined( vms ) || defined( VMS ) || \ + defined( __VMS ) || defined( _M_X64 ) +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN + +#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ + defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ + defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ + defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ + defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ + defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ + defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN + +#elif defined(__arm__) +# ifdef __BIG_ENDIAN +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +# else +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +# endif +#elif 1 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN +#elif 0 /* **** EDIT HERE IF NECESSARY **** */ +# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN +#else +# error Please edit lines 132 or 134 in brg_endian.h to set the platform byte order +#endif + +#endif + +#endif + +// ================================================================================ +// =================== KeccakSponge.h +// ================================================================================ + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakSponge_h_ +#define _KeccakSponge_h_ + +/** + * Function to initialize the state of the Keccak[r, c] sponge function. + * The sponge function is set to the absorbing phase. + * @param state Pointer to the state of the sponge function to be initialized. + * @param rate The value of the rate r. + * @param capacity The value of the capacity c. + * @pre One must have r+c=1600 and the rate a multiple of 64 bits in this implementation. + * @return Zero if successful, 1 otherwise. + */ +int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity); +/** + * Function to give input data for the sponge function to absorb. + * @param state Pointer to the state of the sponge function initialized by InitSponge(). + * @param data Pointer to the input data. + * When @a databitLen is not a multiple of 8, the last bits of data must be + * in the least significant bits of the last byte. + * @param databitLen The number of input bits provided in the input data. + * @pre In the previous call to Absorb(), databitLen was a multiple of 8. + * @pre The sponge function must be in the absorbing phase, + * i.e., Squeeze() must not have been called before. + * @return Zero if successful, 1 otherwise. + */ +int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen); +/** + * Function to squeeze output data from the sponge function. + * If the sponge function was in the absorbing phase, this function + * switches it to the squeezing phase. + * @param state Pointer to the state of the sponge function initialized by InitSponge(). + * @param output Pointer to the buffer where to store the output data. + * @param outputLength The number of output bits desired. + * It must be a multiple of 8. + * @return Zero if successful, 1 otherwise. + */ +int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength); + +#endif + +// ================================================================================ +// =================== KeccakF-1600-int-set.h +// ================================================================================ + + +#define ProvideFast576 +#define ProvideFast832 +#define ProvideFast1024 +#define ProvideFast1088 +#define ProvideFast1152 +#define ProvideFast1344 + + +// ================================================================================ +// =================== KeccakF-1600-interface.h +// ================================================================================ + + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakPermutationInterface_h_ +#define _KeccakPermutationInterface_h_ + +//#include "KeccakF-1600-int-set.h" + +void KeccakInitialize( void ); +void KeccakInitializeState(unsigned char *state); +void KeccakPermutation(unsigned char *state); +#ifdef ProvideFast576 +void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data); +#endif +#ifdef ProvideFast832 +void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data); +#endif +#ifdef ProvideFast1024 +void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data); +#endif +#ifdef ProvideFast1088 +void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data); +#endif +#ifdef ProvideFast1152 +void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data); +#endif +#ifdef ProvideFast1344 +void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data); +#endif +void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount); +#ifdef ProvideFast1024 +void KeccakExtract1024bits(const unsigned char *state, unsigned char *data); +#endif +void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount); + +#endif + + +// ================================================================================ +// =================== KeccakF-1600-opt32-settings.h +// ================================================================================ + + +#define Unrolling 2 +//#define UseBebigokimisa +//#define UseInterleaveTables +#define UseSchedule 3 + + +// ================================================================================ +// =================== KeccakF-1600-unrolling.macros +// ================================================================================ + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#if (Unrolling == 24) +#define rounds \ + prepareTheta \ + thetaRhoPiChiIotaPrepareTheta( 0, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 1, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 2, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 3, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 4, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 5, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 6, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 7, E, A) \ + thetaRhoPiChiIotaPrepareTheta( 8, A, E) \ + thetaRhoPiChiIotaPrepareTheta( 9, E, A) \ + thetaRhoPiChiIotaPrepareTheta(10, A, E) \ + thetaRhoPiChiIotaPrepareTheta(11, E, A) \ + thetaRhoPiChiIotaPrepareTheta(12, A, E) \ + thetaRhoPiChiIotaPrepareTheta(13, E, A) \ + thetaRhoPiChiIotaPrepareTheta(14, A, E) \ + thetaRhoPiChiIotaPrepareTheta(15, E, A) \ + thetaRhoPiChiIotaPrepareTheta(16, A, E) \ + thetaRhoPiChiIotaPrepareTheta(17, E, A) \ + thetaRhoPiChiIotaPrepareTheta(18, A, E) \ + thetaRhoPiChiIotaPrepareTheta(19, E, A) \ + thetaRhoPiChiIotaPrepareTheta(20, A, E) \ + thetaRhoPiChiIotaPrepareTheta(21, E, A) \ + thetaRhoPiChiIotaPrepareTheta(22, A, E) \ + thetaRhoPiChiIota(23, E, A) \ + copyToState(state, A) +#elif (Unrolling == 12) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i+=12) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \ + } \ + copyToState(state, A) +#elif (Unrolling == 8) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i+=8) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+6, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+7, E, A) \ + } \ + copyToState(state, A) +#elif (Unrolling == 6) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i+=6) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \ + } \ + copyToState(state, A) +#elif (Unrolling == 4) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i+=4) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \ + } \ + copyToState(state, A) +#elif (Unrolling == 3) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i+=3) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \ + copyStateVariables(A, E) \ + } \ + copyToState(state, A) +#elif (Unrolling == 2) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i+=2) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \ + } \ + copyToState(state, A) +#elif (Unrolling == 1) +#define rounds \ + prepareTheta \ + for(i=0; i<24; i++) { \ + thetaRhoPiChiIotaPrepareTheta(i , A, E) \ + copyStateVariables(A, E) \ + } \ + copyToState(state, A) +#else +#error "Unrolling is not correctly specified!" +#endif + + +// ================================================================================ +// =================== KeccakF-1600-32-rvk.macros +// ================================================================================ + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by Ronny Van Keer, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +static const UINT32 KeccakF1600RoundConstants_int2[2*24] = +{ + 0x00000001UL, 0x00000000UL, + 0x00000000UL, 0x00000089UL, + 0x00000000UL, 0x8000008bUL, + 0x00000000UL, 0x80008080UL, + 0x00000001UL, 0x0000008bUL, + 0x00000001UL, 0x00008000UL, + 0x00000001UL, 0x80008088UL, + 0x00000001UL, 0x80000082UL, + 0x00000000UL, 0x0000000bUL, + 0x00000000UL, 0x0000000aUL, + 0x00000001UL, 0x00008082UL, + 0x00000000UL, 0x00008003UL, + 0x00000001UL, 0x0000808bUL, + 0x00000001UL, 0x8000000bUL, + 0x00000001UL, 0x8000008aUL, + 0x00000001UL, 0x80000081UL, + 0x00000000UL, 0x80000081UL, + 0x00000000UL, 0x80000008UL, + 0x00000000UL, 0x00000083UL, + 0x00000000UL, 0x80008003UL, + 0x00000001UL, 0x80008088UL, + 0x00000000UL, 0x80000088UL, + 0x00000001UL, 0x00008000UL, + 0x00000000UL, 0x80008082UL +}; + +#undef rounds + +#define rounds \ +{ \ + UINT32 Da0, De0, Di0, Do0, Du0; \ + UINT32 Da1, De1, Di1, Do1, Du1; \ + UINT32 Ba, Be, Bi, Bo, Bu; \ + UINT32 Aba0, Abe0, Abi0, Abo0, Abu0; \ + UINT32 Aba1, Abe1, Abi1, Abo1, Abu1; \ + UINT32 Aga0, Age0, Agi0, Ago0, Agu0; \ + UINT32 Aga1, Age1, Agi1, Ago1, Agu1; \ + UINT32 Aka0, Ake0, Aki0, Ako0, Aku0; \ + UINT32 Aka1, Ake1, Aki1, Ako1, Aku1; \ + UINT32 Ama0, Ame0, Ami0, Amo0, Amu0; \ + UINT32 Ama1, Ame1, Ami1, Amo1, Amu1; \ + UINT32 Asa0, Ase0, Asi0, Aso0, Asu0; \ + UINT32 Asa1, Ase1, Asi1, Aso1, Asu1; \ + UINT32 Cw, Cx, Cy, Cz; \ + UINT32 Eba0, Ebe0, Ebi0, Ebo0, Ebu0; \ + UINT32 Eba1, Ebe1, Ebi1, Ebo1, Ebu1; \ + UINT32 Ega0, Ege0, Egi0, Ego0, Egu0; \ + UINT32 Ega1, Ege1, Egi1, Ego1, Egu1; \ + UINT32 Eka0, Eke0, Eki0, Eko0, Eku0; \ + UINT32 Eka1, Eke1, Eki1, Eko1, Eku1; \ + UINT32 Ema0, Eme0, Emi0, Emo0, Emu0; \ + UINT32 Ema1, Eme1, Emi1, Emo1, Emu1; \ + UINT32 Esa0, Ese0, Esi0, Eso0, Esu0; \ + UINT32 Esa1, Ese1, Esi1, Eso1, Esu1; \ + const UINT32 * pRoundConstants = KeccakF1600RoundConstants_int2; \ + UINT32 i; \ +\ + copyFromState(A, state) \ +\ + for( i = 12; i != 0; --i ) { \ + Cx = Abu0^Agu0^Aku0^Amu0^Asu0; \ + Du1 = Abe1^Age1^Ake1^Ame1^Ase1; \ + Da0 = Cx^ROL32(Du1, 1); \ + Cz = Abu1^Agu1^Aku1^Amu1^Asu1; \ + Du0 = Abe0^Age0^Ake0^Ame0^Ase0; \ + Da1 = Cz^Du0; \ +\ + Cw = Abi0^Agi0^Aki0^Ami0^Asi0; \ + Do0 = Cw^ROL32(Cz, 1); \ + Cy = Abi1^Agi1^Aki1^Ami1^Asi1; \ + Do1 = Cy^Cx; \ +\ + Cx = Aba0^Aga0^Aka0^Ama0^Asa0; \ + De0 = Cx^ROL32(Cy, 1); \ + Cz = Aba1^Aga1^Aka1^Ama1^Asa1; \ + De1 = Cz^Cw; \ +\ + Cy = Abo1^Ago1^Ako1^Amo1^Aso1; \ + Di0 = Du0^ROL32(Cy, 1); \ + Cw = Abo0^Ago0^Ako0^Amo0^Aso0; \ + Di1 = Du1^Cw; \ +\ + Du0 = Cw^ROL32(Cz, 1); \ + Du1 = Cy^Cx; \ +\ + Aba0 ^= Da0; \ + Ba = Aba0; \ + Age0 ^= De0; \ + Be = ROL32(Age0, 22); \ + Aki1 ^= Di1; \ + Bi = ROL32(Aki1, 22); \ + Amo1 ^= Do1; \ + Bo = ROL32(Amo1, 11); \ + Asu0 ^= Du0; \ + Bu = ROL32(Asu0, 7); \ + Eba0 = Ba ^((~Be)& Bi ) ^ *(pRoundConstants++); \ + Ebe0 = Be ^((~Bi)& Bo ); \ + Ebi0 = Bi ^((~Bo)& Bu ); \ + Ebo0 = Bo ^((~Bu)& Ba ); \ + Ebu0 = Bu ^((~Ba)& Be ); \ +\ + Abo0 ^= Do0; \ + Ba = ROL32(Abo0, 14); \ + Agu0 ^= Du0; \ + Be = ROL32(Agu0, 10); \ + Aka1 ^= Da1; \ + Bi = ROL32(Aka1, 2); \ + Ame1 ^= De1; \ + Bo = ROL32(Ame1, 23); \ + Asi1 ^= Di1; \ + Bu = ROL32(Asi1, 31); \ + Ega0 = Ba ^((~Be)& Bi ); \ + Ege0 = Be ^((~Bi)& Bo ); \ + Egi0 = Bi ^((~Bo)& Bu ); \ + Ego0 = Bo ^((~Bu)& Ba ); \ + Egu0 = Bu ^((~Ba)& Be ); \ +\ + Abe1 ^= De1; \ + Ba = ROL32(Abe1, 1); \ + Agi0 ^= Di0; \ + Be = ROL32(Agi0, 3); \ + Ako1 ^= Do1; \ + Bi = ROL32(Ako1, 13); \ + Amu0 ^= Du0; \ + Bo = ROL32(Amu0, 4); \ + Asa0 ^= Da0; \ + Bu = ROL32(Asa0, 9); \ + Eka0 = Ba ^((~Be)& Bi ); \ + Eke0 = Be ^((~Bi)& Bo ); \ + Eki0 = Bi ^((~Bo)& Bu ); \ + Eko0 = Bo ^((~Bu)& Ba ); \ + Eku0 = Bu ^((~Ba)& Be ); \ +\ + Abu1 ^= Du1; \ + Ba = ROL32(Abu1, 14); \ + Aga0 ^= Da0; \ + Be = ROL32(Aga0, 18); \ + Ake0 ^= De0; \ + Bi = ROL32(Ake0, 5); \ + Ami1 ^= Di1; \ + Bo = ROL32(Ami1, 8); \ + Aso0 ^= Do0; \ + Bu = ROL32(Aso0, 28); \ + Ema0 = Ba ^((~Be)& Bi ); \ + Eme0 = Be ^((~Bi)& Bo ); \ + Emi0 = Bi ^((~Bo)& Bu ); \ + Emo0 = Bo ^((~Bu)& Ba ); \ + Emu0 = Bu ^((~Ba)& Be ); \ +\ + Abi0 ^= Di0; \ + Ba = ROL32(Abi0, 31); \ + Ago1 ^= Do1; \ + Be = ROL32(Ago1, 28); \ + Aku1 ^= Du1; \ + Bi = ROL32(Aku1, 20); \ + Ama1 ^= Da1; \ + Bo = ROL32(Ama1, 21); \ + Ase0 ^= De0; \ + Bu = ROL32(Ase0, 1); \ + Esa0 = Ba ^((~Be)& Bi ); \ + Ese0 = Be ^((~Bi)& Bo ); \ + Esi0 = Bi ^((~Bo)& Bu ); \ + Eso0 = Bo ^((~Bu)& Ba ); \ + Esu0 = Bu ^((~Ba)& Be ); \ +\ + Aba1 ^= Da1; \ + Ba = Aba1; \ + Age1 ^= De1; \ + Be = ROL32(Age1, 22); \ + Aki0 ^= Di0; \ + Bi = ROL32(Aki0, 21); \ + Amo0 ^= Do0; \ + Bo = ROL32(Amo0, 10); \ + Asu1 ^= Du1; \ + Bu = ROL32(Asu1, 7); \ + Eba1 = Ba ^((~Be)& Bi ); \ + Eba1 ^= *(pRoundConstants++); \ + Ebe1 = Be ^((~Bi)& Bo ); \ + Ebi1 = Bi ^((~Bo)& Bu ); \ + Ebo1 = Bo ^((~Bu)& Ba ); \ + Ebu1 = Bu ^((~Ba)& Be ); \ +\ + Abo1 ^= Do1; \ + Ba = ROL32(Abo1, 14); \ + Agu1 ^= Du1; \ + Be = ROL32(Agu1, 10); \ + Aka0 ^= Da0; \ + Bi = ROL32(Aka0, 1); \ + Ame0 ^= De0; \ + Bo = ROL32(Ame0, 22); \ + Asi0 ^= Di0; \ + Bu = ROL32(Asi0, 30); \ + Ega1 = Ba ^((~Be)& Bi ); \ + Ege1 = Be ^((~Bi)& Bo ); \ + Egi1 = Bi ^((~Bo)& Bu ); \ + Ego1 = Bo ^((~Bu)& Ba ); \ + Egu1 = Bu ^((~Ba)& Be ); \ +\ + Abe0 ^= De0; \ + Ba = Abe0; \ + Agi1 ^= Di1; \ + Be = ROL32(Agi1, 3); \ + Ako0 ^= Do0; \ + Bi = ROL32(Ako0, 12); \ + Amu1 ^= Du1; \ + Bo = ROL32(Amu1, 4); \ + Asa1 ^= Da1; \ + Bu = ROL32(Asa1, 9); \ + Eka1 = Ba ^((~Be)& Bi ); \ + Eke1 = Be ^((~Bi)& Bo ); \ + Eki1 = Bi ^((~Bo)& Bu ); \ + Eko1 = Bo ^((~Bu)& Ba ); \ + Eku1 = Bu ^((~Ba)& Be ); \ +\ + Abu0 ^= Du0; \ + Ba = ROL32(Abu0, 13); \ + Aga1 ^= Da1; \ + Be = ROL32(Aga1, 18); \ + Ake1 ^= De1; \ + Bi = ROL32(Ake1, 5); \ + Ami0 ^= Di0; \ + Bo = ROL32(Ami0, 7); \ + Aso1 ^= Do1; \ + Bu = ROL32(Aso1, 28); \ + Ema1 = Ba ^((~Be)& Bi ); \ + Eme1 = Be ^((~Bi)& Bo ); \ + Emi1 = Bi ^((~Bo)& Bu ); \ + Emo1 = Bo ^((~Bu)& Ba ); \ + Emu1 = Bu ^((~Ba)& Be ); \ +\ + Abi1 ^= Di1; \ + Ba = ROL32(Abi1, 31); \ + Ago0 ^= Do0; \ + Be = ROL32(Ago0, 27); \ + Aku0 ^= Du0; \ + Bi = ROL32(Aku0, 19); \ + Ama0 ^= Da0; \ + Bo = ROL32(Ama0, 20); \ + Ase1 ^= De1; \ + Bu = ROL32(Ase1, 1); \ + Esa1 = Ba ^((~Be)& Bi ); \ + Ese1 = Be ^((~Bi)& Bo ); \ + Esi1 = Bi ^((~Bo)& Bu ); \ + Eso1 = Bo ^((~Bu)& Ba ); \ + Esu1 = Bu ^((~Ba)& Be ); \ +\ + Cx = Ebu0^Egu0^Eku0^Emu0^Esu0; \ + Du1 = Ebe1^Ege1^Eke1^Eme1^Ese1; \ + Da0 = Cx^ROL32(Du1, 1); \ + Cz = Ebu1^Egu1^Eku1^Emu1^Esu1; \ + Du0 = Ebe0^Ege0^Eke0^Eme0^Ese0; \ + Da1 = Cz^Du0; \ +\ + Cw = Ebi0^Egi0^Eki0^Emi0^Esi0; \ + Do0 = Cw^ROL32(Cz, 1); \ + Cy = Ebi1^Egi1^Eki1^Emi1^Esi1; \ + Do1 = Cy^Cx; \ +\ + Cx = Eba0^Ega0^Eka0^Ema0^Esa0; \ + De0 = Cx^ROL32(Cy, 1); \ + Cz = Eba1^Ega1^Eka1^Ema1^Esa1; \ + De1 = Cz^Cw; \ +\ + Cy = Ebo1^Ego1^Eko1^Emo1^Eso1; \ + Di0 = Du0^ROL32(Cy, 1); \ + Cw = Ebo0^Ego0^Eko0^Emo0^Eso0; \ + Di1 = Du1^Cw; \ +\ + Du0 = Cw^ROL32(Cz, 1); \ + Du1 = Cy^Cx; \ +\ + Eba0 ^= Da0; \ + Ba = Eba0; \ + Ege0 ^= De0; \ + Be = ROL32(Ege0, 22); \ + Eki1 ^= Di1; \ + Bi = ROL32(Eki1, 22); \ + Emo1 ^= Do1; \ + Bo = ROL32(Emo1, 11); \ + Esu0 ^= Du0; \ + Bu = ROL32(Esu0, 7); \ + Aba0 = Ba ^((~Be)& Bi ); \ + Aba0 ^= *(pRoundConstants++); \ + Abe0 = Be ^((~Bi)& Bo ); \ + Abi0 = Bi ^((~Bo)& Bu ); \ + Abo0 = Bo ^((~Bu)& Ba ); \ + Abu0 = Bu ^((~Ba)& Be ); \ +\ + Ebo0 ^= Do0; \ + Ba = ROL32(Ebo0, 14); \ + Egu0 ^= Du0; \ + Be = ROL32(Egu0, 10); \ + Eka1 ^= Da1; \ + Bi = ROL32(Eka1, 2); \ + Eme1 ^= De1; \ + Bo = ROL32(Eme1, 23); \ + Esi1 ^= Di1; \ + Bu = ROL32(Esi1, 31); \ + Aga0 = Ba ^((~Be)& Bi ); \ + Age0 = Be ^((~Bi)& Bo ); \ + Agi0 = Bi ^((~Bo)& Bu ); \ + Ago0 = Bo ^((~Bu)& Ba ); \ + Agu0 = Bu ^((~Ba)& Be ); \ +\ + Ebe1 ^= De1; \ + Ba = ROL32(Ebe1, 1); \ + Egi0 ^= Di0; \ + Be = ROL32(Egi0, 3); \ + Eko1 ^= Do1; \ + Bi = ROL32(Eko1, 13); \ + Emu0 ^= Du0; \ + Bo = ROL32(Emu0, 4); \ + Esa0 ^= Da0; \ + Bu = ROL32(Esa0, 9); \ + Aka0 = Ba ^((~Be)& Bi ); \ + Ake0 = Be ^((~Bi)& Bo ); \ + Aki0 = Bi ^((~Bo)& Bu ); \ + Ako0 = Bo ^((~Bu)& Ba ); \ + Aku0 = Bu ^((~Ba)& Be ); \ +\ + Ebu1 ^= Du1; \ + Ba = ROL32(Ebu1, 14); \ + Ega0 ^= Da0; \ + Be = ROL32(Ega0, 18); \ + Eke0 ^= De0; \ + Bi = ROL32(Eke0, 5); \ + Emi1 ^= Di1; \ + Bo = ROL32(Emi1, 8); \ + Eso0 ^= Do0; \ + Bu = ROL32(Eso0, 28); \ + Ama0 = Ba ^((~Be)& Bi ); \ + Ame0 = Be ^((~Bi)& Bo ); \ + Ami0 = Bi ^((~Bo)& Bu ); \ + Amo0 = Bo ^((~Bu)& Ba ); \ + Amu0 = Bu ^((~Ba)& Be ); \ +\ + Ebi0 ^= Di0; \ + Ba = ROL32(Ebi0, 31); \ + Ego1 ^= Do1; \ + Be = ROL32(Ego1, 28); \ + Eku1 ^= Du1; \ + Bi = ROL32(Eku1, 20); \ + Ema1 ^= Da1; \ + Bo = ROL32(Ema1, 21); \ + Ese0 ^= De0; \ + Bu = ROL32(Ese0, 1); \ + Asa0 = Ba ^((~Be)& Bi ); \ + Ase0 = Be ^((~Bi)& Bo ); \ + Asi0 = Bi ^((~Bo)& Bu ); \ + Aso0 = Bo ^((~Bu)& Ba ); \ + Asu0 = Bu ^((~Ba)& Be ); \ +\ + Eba1 ^= Da1; \ + Ba = Eba1; \ + Ege1 ^= De1; \ + Be = ROL32(Ege1, 22); \ + Eki0 ^= Di0; \ + Bi = ROL32(Eki0, 21); \ + Emo0 ^= Do0; \ + Bo = ROL32(Emo0, 10); \ + Esu1 ^= Du1; \ + Bu = ROL32(Esu1, 7); \ + Aba1 = Ba ^((~Be)& Bi ); \ + Aba1 ^= *(pRoundConstants++); \ + Abe1 = Be ^((~Bi)& Bo ); \ + Abi1 = Bi ^((~Bo)& Bu ); \ + Abo1 = Bo ^((~Bu)& Ba ); \ + Abu1 = Bu ^((~Ba)& Be ); \ +\ + Ebo1 ^= Do1; \ + Ba = ROL32(Ebo1, 14); \ + Egu1 ^= Du1; \ + Be = ROL32(Egu1, 10); \ + Eka0 ^= Da0; \ + Bi = ROL32(Eka0, 1); \ + Eme0 ^= De0; \ + Bo = ROL32(Eme0, 22); \ + Esi0 ^= Di0; \ + Bu = ROL32(Esi0, 30); \ + Aga1 = Ba ^((~Be)& Bi ); \ + Age1 = Be ^((~Bi)& Bo ); \ + Agi1 = Bi ^((~Bo)& Bu ); \ + Ago1 = Bo ^((~Bu)& Ba ); \ + Agu1 = Bu ^((~Ba)& Be ); \ +\ + Ebe0 ^= De0; \ + Ba = Ebe0; \ + Egi1 ^= Di1; \ + Be = ROL32(Egi1, 3); \ + Eko0 ^= Do0; \ + Bi = ROL32(Eko0, 12); \ + Emu1 ^= Du1; \ + Bo = ROL32(Emu1, 4); \ + Esa1 ^= Da1; \ + Bu = ROL32(Esa1, 9); \ + Aka1 = Ba ^((~Be)& Bi ); \ + Ake1 = Be ^((~Bi)& Bo ); \ + Aki1 = Bi ^((~Bo)& Bu ); \ + Ako1 = Bo ^((~Bu)& Ba ); \ + Aku1 = Bu ^((~Ba)& Be ); \ +\ + Ebu0 ^= Du0; \ + Ba = ROL32(Ebu0, 13); \ + Ega1 ^= Da1; \ + Be = ROL32(Ega1, 18); \ + Eke1 ^= De1; \ + Bi = ROL32(Eke1, 5); \ + Emi0 ^= Di0; \ + Bo = ROL32(Emi0, 7); \ + Eso1 ^= Do1; \ + Bu = ROL32(Eso1, 28); \ + Ama1 = Ba ^((~Be)& Bi ); \ + Ame1 = Be ^((~Bi)& Bo ); \ + Ami1 = Bi ^((~Bo)& Bu ); \ + Amo1 = Bo ^((~Bu)& Ba ); \ + Amu1 = Bu ^((~Ba)& Be ); \ +\ + Ebi1 ^= Di1; \ + Ba = ROL32(Ebi1, 31); \ + Ego0 ^= Do0; \ + Be = ROL32(Ego0, 27); \ + Eku0 ^= Du0; \ + Bi = ROL32(Eku0, 19); \ + Ema0 ^= Da0; \ + Bo = ROL32(Ema0, 20); \ + Ese1 ^= De1; \ + Bu = ROL32(Ese1, 1); \ + Asa1 = Ba ^((~Be)& Bi ); \ + Ase1 = Be ^((~Bi)& Bo ); \ + Asi1 = Bi ^((~Bo)& Bu ); \ + Aso1 = Bo ^((~Bu)& Ba ); \ + Asu1 = Bu ^((~Ba)& Be ); \ + } \ + copyToState(state, A) \ +} + +#define copyFromState(X, state) \ + X##ba0 = state[ 0]; \ + X##ba1 = state[ 1]; \ + X##be0 = state[ 2]; \ + X##be1 = state[ 3]; \ + X##bi0 = state[ 4]; \ + X##bi1 = state[ 5]; \ + X##bo0 = state[ 6]; \ + X##bo1 = state[ 7]; \ + X##bu0 = state[ 8]; \ + X##bu1 = state[ 9]; \ + X##ga0 = state[10]; \ + X##ga1 = state[11]; \ + X##ge0 = state[12]; \ + X##ge1 = state[13]; \ + X##gi0 = state[14]; \ + X##gi1 = state[15]; \ + X##go0 = state[16]; \ + X##go1 = state[17]; \ + X##gu0 = state[18]; \ + X##gu1 = state[19]; \ + X##ka0 = state[20]; \ + X##ka1 = state[21]; \ + X##ke0 = state[22]; \ + X##ke1 = state[23]; \ + X##ki0 = state[24]; \ + X##ki1 = state[25]; \ + X##ko0 = state[26]; \ + X##ko1 = state[27]; \ + X##ku0 = state[28]; \ + X##ku1 = state[29]; \ + X##ma0 = state[30]; \ + X##ma1 = state[31]; \ + X##me0 = state[32]; \ + X##me1 = state[33]; \ + X##mi0 = state[34]; \ + X##mi1 = state[35]; \ + X##mo0 = state[36]; \ + X##mo1 = state[37]; \ + X##mu0 = state[38]; \ + X##mu1 = state[39]; \ + X##sa0 = state[40]; \ + X##sa1 = state[41]; \ + X##se0 = state[42]; \ + X##se1 = state[43]; \ + X##si0 = state[44]; \ + X##si1 = state[45]; \ + X##so0 = state[46]; \ + X##so1 = state[47]; \ + X##su0 = state[48]; \ + X##su1 = state[49]; \ + +#define copyToState(state, X) \ + state[ 0] = X##ba0; \ + state[ 1] = X##ba1; \ + state[ 2] = X##be0; \ + state[ 3] = X##be1; \ + state[ 4] = X##bi0; \ + state[ 5] = X##bi1; \ + state[ 6] = X##bo0; \ + state[ 7] = X##bo1; \ + state[ 8] = X##bu0; \ + state[ 9] = X##bu1; \ + state[10] = X##ga0; \ + state[11] = X##ga1; \ + state[12] = X##ge0; \ + state[13] = X##ge1; \ + state[14] = X##gi0; \ + state[15] = X##gi1; \ + state[16] = X##go0; \ + state[17] = X##go1; \ + state[18] = X##gu0; \ + state[19] = X##gu1; \ + state[20] = X##ka0; \ + state[21] = X##ka1; \ + state[22] = X##ke0; \ + state[23] = X##ke1; \ + state[24] = X##ki0; \ + state[25] = X##ki1; \ + state[26] = X##ko0; \ + state[27] = X##ko1; \ + state[28] = X##ku0; \ + state[29] = X##ku1; \ + state[30] = X##ma0; \ + state[31] = X##ma1; \ + state[32] = X##me0; \ + state[33] = X##me1; \ + state[34] = X##mi0; \ + state[35] = X##mi1; \ + state[36] = X##mo0; \ + state[37] = X##mo1; \ + state[38] = X##mu0; \ + state[39] = X##mu1; \ + state[40] = X##sa0; \ + state[41] = X##sa1; \ + state[42] = X##se0; \ + state[43] = X##se1; \ + state[44] = X##si0; \ + state[45] = X##si1; \ + state[46] = X##so0; \ + state[47] = X##so1; \ + state[48] = X##su0; \ + state[49] = X##su1; \ + + +// ================================================================================ +// =================== KeccakF-1600-32.macros +// ================================================================================ + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifdef UseSchedule + #if (UseSchedule == 1) + #include "KeccakF-1600-32-s1.macros" + #elif (UseSchedule == 2) + #include "KeccakF-1600-32-s2.macros" + #elif (UseSchedule == 3) + //#include "KeccakF-1600-32-rvk.macros" + #else + #error "This schedule is not supported." + #endif +#else + #include "KeccakF-1600-32-s1.macros" +#endif + +// ================================================================================ +// =================== KeccakF-1600-opt32.c +// ================================================================================ + + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include +//#include "brg_endian.h" +//#include "KeccakF-1600-opt32-settings.h" +//#include "KeccakF-1600-interface.h" + + + +#ifdef UseInterleaveTables +int interleaveTablesBuilt = 0; +UINT16 interleaveTable[65536]; +UINT16 deinterleaveTable[65536]; + +void buildInterleaveTables() +{ + UINT32 i, j; + UINT16 x; + + if (!interleaveTablesBuilt) { + for(i=0; i<65536; i++) { + x = 0; + for(j=0; j<16; j++) { + if (i & (1 << j)) + x |= (1 << (j/2 + 8*(j%2))); + } + interleaveTable[i] = x; + deinterleaveTable[x] = (UINT16)i; + } + interleaveTablesBuilt = 1; + } +} + +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) + +#define xor2bytesIntoInterleavedWords(even, odd, source, j) \ + i##j = interleaveTable[((const UINT16*)source)[j]]; \ + ((UINT8*)even)[j] ^= i##j & 0xFF; \ + ((UINT8*)odd)[j] ^= i##j >> 8; + +#define setInterleavedWordsInto2bytes(dest, even, odd, j) \ + d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \ + ((UINT16*)dest)[j] = d##j; + +#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) + +#define xor2bytesIntoInterleavedWords(even, odd, source, j) \ + i##j = interleaveTable[source[2*j] ^ ((UINT16)source[2*j+1] << 8)]; \ + *even ^= (i##j & 0xFF) << (j*8); \ + *odd ^= ((i##j >> 8) & 0xFF) << (j*8); + +#define setInterleavedWordsInto2bytes(dest, even, odd, j) \ + d##j = deinterleaveTable[((even >> (j*8)) & 0xFF) ^ (((odd >> (j*8)) & 0xFF) << 8)]; \ + dest[2*j] = d##j & 0xFF; \ + dest[2*j+1] = d##j >> 8; + +#endif // Endianness + +void xor8bytesIntoInterleavedWords(UINT32 *even, UINT32 *odd, const UINT8* source) +{ + UINT16 i0, i1, i2, i3; + + xor2bytesIntoInterleavedWords(even, odd, source, 0) + xor2bytesIntoInterleavedWords(even, odd, source, 1) + xor2bytesIntoInterleavedWords(even, odd, source, 2) + xor2bytesIntoInterleavedWords(even, odd, source, 3) +} + +#define xorLanesIntoState(laneCount, state, input) \ + { \ + int i; \ + for(i=0; i<(laneCount); i++) \ + xor8bytesIntoInterleavedWords(state+i*2, state+i*2+1, input+i*8); \ + } + +void setInterleavedWordsInto8bytes(UINT8* dest, UINT32 even, UINT32 odd) +{ + UINT16 d0, d1, d2, d3; + + setInterleavedWordsInto2bytes(dest, even, odd, 0) + setInterleavedWordsInto2bytes(dest, even, odd, 1) + setInterleavedWordsInto2bytes(dest, even, odd, 2) + setInterleavedWordsInto2bytes(dest, even, odd, 3) +} + +#define extractLanes(laneCount, state, data) \ + { \ + int i; \ + for(i=0; i<(laneCount); i++) \ + setInterleavedWordsInto8bytes(data+i*8, ((UINT32*)state)[i*2], ((UINT32*)state)[i*2+1]); \ + } + +#else // No interleaving tables + +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) + +// Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +#define xorInterleavedLE(rateInLanes, state, input) \ + { \ + const UINT32 * pI = (const UINT32 *)input; \ + UINT32 * pS = state; \ + UINT32 t, x0, x1; \ + int i; \ + for (i = (rateInLanes)-1; i >= 0; --i) \ + { \ + x0 = *(pI++); \ + t = (x0 ^ (x0 >> 1)) & 0x22222222UL; x0 = x0 ^ t ^ (t << 1); \ + t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0CUL; x0 = x0 ^ t ^ (t << 2); \ + t = (x0 ^ (x0 >> 4)) & 0x00F000F0UL; x0 = x0 ^ t ^ (t << 4); \ + t = (x0 ^ (x0 >> 8)) & 0x0000FF00UL; x0 = x0 ^ t ^ (t << 8); \ + x1 = *(pI++); \ + t = (x1 ^ (x1 >> 1)) & 0x22222222UL; x1 = x1 ^ t ^ (t << 1); \ + t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0CUL; x1 = x1 ^ t ^ (t << 2); \ + t = (x1 ^ (x1 >> 4)) & 0x00F000F0UL; x1 = x1 ^ t ^ (t << 4); \ + t = (x1 ^ (x1 >> 8)) & 0x0000FF00UL; x1 = x1 ^ t ^ (t << 8); \ + *(pS++) ^= (UINT16)x0 | (x1 << 16); \ + *(pS++) ^= (x0 >> 16) | (x1 & 0xFFFF0000); \ + } \ + } + +#define xorLanesIntoState(laneCount, state, input) \ + xorInterleavedLE(laneCount, state, input) + +#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) + +// Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +UINT64 toInterleaving(UINT64 x) +{ + UINT64 t; + + t = (x ^ (x >> 1)) & 0x2222222222222222ULL; x = x ^ t ^ (t << 1); + t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CULL; x = x ^ t ^ (t << 2); + t = (x ^ (x >> 4)) & 0x00F000F000F000F0ULL; x = x ^ t ^ (t << 4); + t = (x ^ (x >> 8)) & 0x0000FF000000FF00ULL; x = x ^ t ^ (t << 8); + t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL; x = x ^ t ^ (t << 16); + + return x; +} + +void xor8bytesIntoInterleavedWords(UINT32* evenAndOdd, const UINT8* source) +{ + // This can be optimized + UINT64 sourceWord = + (UINT64)source[0] + ^ (((UINT64)source[1]) << 8) + ^ (((UINT64)source[2]) << 16) + ^ (((UINT64)source[3]) << 24) + ^ (((UINT64)source[4]) << 32) + ^ (((UINT64)source[5]) << 40) + ^ (((UINT64)source[6]) << 48) + ^ (((UINT64)source[7]) << 56); + UINT64 evenAndOddWord = toInterleaving(sourceWord); + evenAndOdd[0] ^= (UINT32)evenAndOddWord; + evenAndOdd[1] ^= (UINT32)(evenAndOddWord >> 32); +} + +#define xorLanesIntoState(laneCount, state, input) \ + { \ + int i; \ + for(i=0; i<(laneCount); i++) \ + xor8bytesIntoInterleavedWords(state+i*2, input+i*8); \ + } + +#endif // Endianness + +// Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 +UINT64 fromInterleaving(UINT64 x) +{ + UINT64 t; + + t = (x ^ (x >> 16)) & 0x00000000FFFF0000ULL; x = x ^ t ^ (t << 16); + t = (x ^ (x >> 8)) & 0x0000FF000000FF00ULL; x = x ^ t ^ (t << 8); + t = (x ^ (x >> 4)) & 0x00F000F000F000F0ULL; x = x ^ t ^ (t << 4); + t = (x ^ (x >> 2)) & 0x0C0C0C0C0C0C0C0CULL; x = x ^ t ^ (t << 2); + t = (x ^ (x >> 1)) & 0x2222222222222222ULL; x = x ^ t ^ (t << 1); + + return x; +} + +void setInterleavedWordsInto8bytes(UINT8* dest, UINT32* evenAndOdd) +{ +#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN) + ((UINT64*)dest)[0] = fromInterleaving(*(UINT64*)evenAndOdd); +#else // (PLATFORM_BYTE_ORDER == IS_BIG_ENDIAN) + // This can be optimized + UINT64 evenAndOddWord = (UINT64)evenAndOdd[0] ^ ((UINT64)evenAndOdd[1] << 32); + UINT64 destWord = fromInterleaving(evenAndOddWord); + dest[0] = destWord & 0xFF; + dest[1] = (destWord >> 8) & 0xFF; + dest[2] = (destWord >> 16) & 0xFF; + dest[3] = (destWord >> 24) & 0xFF; + dest[4] = (destWord >> 32) & 0xFF; + dest[5] = (destWord >> 40) & 0xFF; + dest[6] = (destWord >> 48) & 0xFF; + dest[7] = (destWord >> 56) & 0xFF; +#endif // Endianness +} + +#define extractLanes(laneCount, state, data) \ + { \ + int i; \ + for(i=0; i<(laneCount); i++) \ + setInterleavedWordsInto8bytes(data+i*8, (UINT32*)state+i*2); \ + } + +#endif // With or without interleaving tables + +#if defined(_MSC_VER) +#define ROL32(a, offset) _rotl(a, offset) +#elif (defined (__arm__) && defined(__ARMCC_VERSION)) +#define ROL32(a, offset) __ror(a, 32-(offset)) +#else +#define ROL32(a, offset) ((((UINT32)a) << (offset)) ^ (((UINT32)a) >> (32-(offset)))) +#endif + +//#include "KeccakF-1600-unrolling.macros" +//#include "KeccakF-1600-32.macros" + +#if (UseSchedule == 3) + +#ifdef UseBebigokimisa +#error "No lane complementing with schedule 3." +#endif + +#if (Unrolling != 2) +#error "Only unrolling 2 is supported by schedule 3." +#endif + +void KeccakPermutationOnWords(UINT32 *state) +{ + rounds +} + +void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount) +{ + xorLanesIntoState(laneCount, state, input) + rounds +} + +#ifdef ProvideFast576 +void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input) +{ + xorLanesIntoState(9, state, input) + rounds +} +#endif + +#ifdef ProvideFast832 +void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input) +{ + xorLanesIntoState(13, state, input) + rounds +} +#endif + +#ifdef ProvideFast1024 +void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input) +{ + xorLanesIntoState(16, state, input) + rounds +} +#endif + +#ifdef ProvideFast1088 +void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input) +{ + xorLanesIntoState(17, state, input) + rounds +} +#endif + +#ifdef ProvideFast1152 +void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input) +{ + xorLanesIntoState(18, state, input) + rounds +} +#endif + +#ifdef ProvideFast1344 +void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input) +{ + xorLanesIntoState(21, state, input) + rounds +} +#endif + +#else // (Schedule != 3) + +void KeccakPermutationOnWords(UINT32 *state) +{ + declareABCDE +#if (Unrolling != 24) + unsigned int i; +#endif + + copyFromState(A, state) + rounds +} + +void KeccakPermutationOnWordsAfterXoring(UINT32 *state, const UINT8 *input, unsigned int laneCount) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(laneCount, state, input) + copyFromState(A, state) + rounds +} + +#ifdef ProvideFast576 +void KeccakPermutationOnWordsAfterXoring576bits(UINT32 *state, const UINT8 *input) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(9, state, input) + copyFromState(A, state) + rounds +} +#endif + +#ifdef ProvideFast832 +void KeccakPermutationOnWordsAfterXoring832bits(UINT32 *state, const UINT8 *input) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(13, state, input) + copyFromState(A, state) + rounds +} +#endif + +#ifdef ProvideFast1024 +void KeccakPermutationOnWordsAfterXoring1024bits(UINT32 *state, const UINT8 *input) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(16, state, input) + copyFromState(A, state) + rounds +} +#endif + +#ifdef ProvideFast1088 +void KeccakPermutationOnWordsAfterXoring1088bits(UINT32 *state, const UINT8 *input) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(17, state, input) + copyFromState(A, state) + rounds +} +#endif + +#ifdef ProvideFast1152 +void KeccakPermutationOnWordsAfterXoring1152bits(UINT32 *state, const UINT8 *input) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(18, state, input) + copyFromState(A, state) + rounds +} +#endif + +#ifdef ProvideFast1344 +void KeccakPermutationOnWordsAfterXoring1344bits(UINT32 *state, const UINT8 *input) +{ + declareABCDE + unsigned int i; + + xorLanesIntoState(21, state, input) + copyFromState(A, state) + rounds +} +#endif + +#endif + +void KeccakInitialize() +{ +#ifdef UseInterleaveTables + buildInterleaveTables(); +#endif +} + +void KeccakInitializeState(unsigned char *state) +{ + memset(state, 0, 200); +#ifdef UseBebigokimisa + ((UINT32*)state)[ 2] = ~(UINT32)0; + ((UINT32*)state)[ 3] = ~(UINT32)0; + ((UINT32*)state)[ 4] = ~(UINT32)0; + ((UINT32*)state)[ 5] = ~(UINT32)0; + ((UINT32*)state)[16] = ~(UINT32)0; + ((UINT32*)state)[17] = ~(UINT32)0; + ((UINT32*)state)[24] = ~(UINT32)0; + ((UINT32*)state)[25] = ~(UINT32)0; + ((UINT32*)state)[34] = ~(UINT32)0; + ((UINT32*)state)[35] = ~(UINT32)0; + ((UINT32*)state)[40] = ~(UINT32)0; + ((UINT32*)state)[41] = ~(UINT32)0; +#endif +} + +void KeccakPermutation(unsigned char *state) +{ + // We assume the state is always stored as interleaved 32-bit words + KeccakPermutationOnWords((UINT32*)state); +} + +#ifdef ProvideFast576 +void KeccakAbsorb576bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationOnWordsAfterXoring576bits((UINT32*)state, data); +} +#endif + +#ifdef ProvideFast832 +void KeccakAbsorb832bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationOnWordsAfterXoring832bits((UINT32*)state, data); +} +#endif + +#ifdef ProvideFast1024 +void KeccakAbsorb1024bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationOnWordsAfterXoring1024bits((UINT32*)state, data); +} +#endif + +#ifdef ProvideFast1088 +void KeccakAbsorb1088bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationOnWordsAfterXoring1088bits((UINT32*)state, data); +} +#endif + +#ifdef ProvideFast1152 +void KeccakAbsorb1152bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationOnWordsAfterXoring1152bits((UINT32*)state, data); +} +#endif + +#ifdef ProvideFast1344 +void KeccakAbsorb1344bits(unsigned char *state, const unsigned char *data) +{ + KeccakPermutationOnWordsAfterXoring1344bits((UINT32*)state, data); +} +#endif + +void KeccakAbsorb(unsigned char *state, const unsigned char *data, unsigned int laneCount) +{ + KeccakPermutationOnWordsAfterXoring((UINT32*)state, data, laneCount); +} + +#ifdef ProvideFast1024 +void KeccakExtract1024bits(const unsigned char *state, unsigned char *data) +{ + extractLanes(16, state, data) +#ifdef UseBebigokimisa + ((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2]; + ((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3]; + ((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4]; + ((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5]; + ((UINT32*)data)[16] = ~((UINT32*)data)[16]; + ((UINT32*)data)[17] = ~((UINT32*)data)[17]; + ((UINT32*)data)[24] = ~((UINT32*)data)[24]; + ((UINT32*)data)[25] = ~((UINT32*)data)[25]; +#endif +} +#endif + +void KeccakExtract(const unsigned char *state, unsigned char *data, unsigned int laneCount) +{ + extractLanes((int)laneCount, state, data) +#ifdef UseBebigokimisa + if (laneCount > 1) { + ((UINT32*)data)[ 2] = ~((UINT32*)data)[ 2]; + ((UINT32*)data)[ 3] = ~((UINT32*)data)[ 3]; + if (laneCount > 2) { + ((UINT32*)data)[ 4] = ~((UINT32*)data)[ 4]; + ((UINT32*)data)[ 5] = ~((UINT32*)data)[ 5]; + if (laneCount > 8) { + ((UINT32*)data)[16] = ~((UINT32*)data)[16]; + ((UINT32*)data)[17] = ~((UINT32*)data)[17]; + if (laneCount > 12) { + ((UINT32*)data)[24] = ~((UINT32*)data)[24]; + ((UINT32*)data)[25] = ~((UINT32*)data)[25]; + if (laneCount > 17) { + ((UINT32*)data)[34] = ~((UINT32*)data)[34]; + ((UINT32*)data)[35] = ~((UINT32*)data)[35]; + if (laneCount > 20) { + ((UINT32*)data)[40] = ~((UINT32*)data)[40]; + ((UINT32*)data)[41] = ~((UINT32*)data)[41]; + } + } + } + } + } + } +#endif +} + + +// ================================================================================ +// =================== KeccakSponge.c +// ================================================================================ + + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include +//#include "KeccakSponge.h" +//#include "KeccakF-1600-interface.h" +#ifdef KeccakReference +//#include "displayIntermediateValues.h" +#endif + +int InitSponge(spongeState *state, unsigned int rate, unsigned int capacity) +{ + if (rate+capacity != 1600) + return 1; + if ((rate <= 0) || (rate >= 1600) || ((rate % 64) != 0)) + return 1; + KeccakInitialize(); + state->rate = rate; + state->capacity = capacity; + state->fixedOutputLength = 0; + KeccakInitializeState(state->state); + memset(state->dataQueue, 0, KeccakMaximumRateInBytes); + state->bitsInQueue = 0; + state->squeezing = 0; + state->bitsAvailableForSqueezing = 0; + + return 0; +} + +void AbsorbQueue(spongeState *state) +{ + // state->bitsInQueue is assumed to be equal to state->rate + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed", state->dataQueue, state->rate/8); + #endif +#ifdef ProvideFast576 + if (state->rate == 576) + KeccakAbsorb576bits(state->state, state->dataQueue); + else +#endif +#ifdef ProvideFast832 + if (state->rate == 832) + KeccakAbsorb832bits(state->state, state->dataQueue); + else +#endif +#ifdef ProvideFast1024 + if (state->rate == 1024) + KeccakAbsorb1024bits(state->state, state->dataQueue); + else +#endif +#ifdef ProvideFast1088 + if (state->rate == 1088) + KeccakAbsorb1088bits(state->state, state->dataQueue); + else +#endif +#ifdef ProvideFast1152 + if (state->rate == 1152) + KeccakAbsorb1152bits(state->state, state->dataQueue); + else +#endif +#ifdef ProvideFast1344 + if (state->rate == 1344) + KeccakAbsorb1344bits(state->state, state->dataQueue); + else +#endif + KeccakAbsorb(state->state, state->dataQueue, state->rate/64); + state->bitsInQueue = 0; +} + +int Absorb(spongeState *state, const unsigned char *data, unsigned long long databitlen) +{ + unsigned long long i, j, wholeBlocks; + unsigned int partialBlock, partialByte; + const unsigned char *curData; + + if ((state->bitsInQueue % 8) != 0) + return 1; // Only the last call may contain a partial byte + if (state->squeezing) + return 1; // Too late for additional input + + i = 0; + while(i < databitlen) { + if ((state->bitsInQueue == 0) && (databitlen >= state->rate) && (i <= (databitlen-state->rate))) { + wholeBlocks = (databitlen-i)/state->rate; + curData = data+i/8; +#ifdef ProvideFast576 + if (state->rate == 576) { + for(j=0; jrate/8); + #endif + KeccakAbsorb576bits(state->state, curData); + } + } + else +#endif +#ifdef ProvideFast832 + if (state->rate == 832) { + for(j=0; jrate/8); + #endif + KeccakAbsorb832bits(state->state, curData); + } + } + else +#endif +#ifdef ProvideFast1024 + if (state->rate == 1024) { + for(j=0; jrate/8); + #endif + KeccakAbsorb1024bits(state->state, curData); + } + } + else +#endif +#ifdef ProvideFast1088 + if (state->rate == 1088) { + for(j=0; jrate/8); + #endif + KeccakAbsorb1088bits(state->state, curData); + } + } + else +#endif +#ifdef ProvideFast1152 + if (state->rate == 1152) { + for(j=0; jrate/8); + #endif + KeccakAbsorb1152bits(state->state, curData); + } + } + else +#endif +#ifdef ProvideFast1344 + if (state->rate == 1344) { + for(j=0; jrate/8); + #endif + KeccakAbsorb1344bits(state->state, curData); + } + } + else +#endif + { + for(j=0; jrate/8) { + #ifdef KeccakReference + displayBytes(1, "Block to be absorbed", curData, state->rate/8); + #endif + KeccakAbsorb(state->state, curData, state->rate/64); + } + } + i += wholeBlocks*state->rate; + } + else { + partialBlock = (unsigned int)(databitlen - i); + if (partialBlock+state->bitsInQueue > state->rate) + partialBlock = state->rate-state->bitsInQueue; + partialByte = partialBlock % 8; + partialBlock -= partialByte; + memcpy(state->dataQueue+state->bitsInQueue/8, data+i/8, partialBlock/8); + state->bitsInQueue += partialBlock; + i += partialBlock; + if (state->bitsInQueue == state->rate) + AbsorbQueue(state); + if (partialByte > 0) { + unsigned char mask = (1 << partialByte)-1; + state->dataQueue[state->bitsInQueue/8] = data[i/8] & mask; + state->bitsInQueue += partialByte; + i += partialByte; + } + } + } + return 0; +} + +void PadAndSwitchToSqueezingPhase(spongeState *state) +{ + // Note: the bits are numbered from 0=LSB to 7=MSB + if (state->bitsInQueue + 1 == state->rate) { + state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); + AbsorbQueue(state); + memset(state->dataQueue, 0, state->rate/8); + } + else { + memset(state->dataQueue + (state->bitsInQueue+7)/8, 0, state->rate/8 - (state->bitsInQueue+7)/8); + state->dataQueue[state->bitsInQueue/8 ] |= 1 << (state->bitsInQueue % 8); + } + state->dataQueue[(state->rate-1)/8] |= 1 << ((state->rate-1) % 8); + AbsorbQueue(state); + + #ifdef KeccakReference + displayText(1, "--- Switching to squeezing phase ---"); + #endif +#ifdef ProvideFast1024 + if (state->rate == 1024) { + KeccakExtract1024bits(state->state, state->dataQueue); + state->bitsAvailableForSqueezing = 1024; + } + else +#endif + { + KeccakExtract(state->state, state->dataQueue, state->rate/64); + state->bitsAvailableForSqueezing = state->rate; + } + #ifdef KeccakReference + displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8); + #endif + state->squeezing = 1; +} + +int Squeeze(spongeState *state, unsigned char *output, unsigned long long outputLength) +{ + unsigned long long i; + unsigned int partialBlock; + + if (!state->squeezing) + PadAndSwitchToSqueezingPhase(state); + if ((outputLength % 8) != 0) + return 1; // Only multiple of 8 bits are allowed, truncation can be done at user level + + i = 0; + while(i < outputLength) { + if (state->bitsAvailableForSqueezing == 0) { + KeccakPermutation(state->state); +#ifdef ProvideFast1024 + if (state->rate == 1024) { + KeccakExtract1024bits(state->state, state->dataQueue); + state->bitsAvailableForSqueezing = 1024; + } + else +#endif + { + KeccakExtract(state->state, state->dataQueue, state->rate/64); + state->bitsAvailableForSqueezing = state->rate; + } + #ifdef KeccakReference + displayBytes(1, "Block available for squeezing", state->dataQueue, state->bitsAvailableForSqueezing/8); + #endif + } + partialBlock = state->bitsAvailableForSqueezing; + if ((unsigned long long)partialBlock > outputLength - i) + partialBlock = (unsigned int)(outputLength - i); + memcpy(output+i/8, state->dataQueue+(state->rate-state->bitsAvailableForSqueezing)/8, partialBlock/8); + state->bitsAvailableForSqueezing -= partialBlock; + i += partialBlock; + } + return 0; +} + + + +// ================================================================================ +// =================== KeccakNISTInterface.h +// ================================================================================ + + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#ifndef _KeccakNISTInterface_h_ +#define _KeccakNISTInterface_h_ + +//#include "KeccakSponge.h" + +typedef unsigned char BitSequence; +typedef unsigned long long DataLength; +typedef enum { SUCCESS = 0, FAIL = 1, BAD_HASHLEN = 2 } HashReturn; + +typedef spongeState hashState; + +/** + * Function to initialize the state of the Keccak[r, c] sponge function. + * The rate r and capacity c values are determined from @a hashbitlen. + * @param state Pointer to the state of the sponge function to be initialized. + * @param hashbitlen The desired number of output bits, + * or 0 for Keccak[] with default parameters + * and arbitrarily-long output. + * @pre The value of hashbitlen must be one of 0, 224, 256, 384 and 512. + * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect. + */ +HashReturn Init(hashState *state, int hashbitlen); +/** + * Function to give input data for the sponge function to absorb. + * @param state Pointer to the state of the sponge function initialized by Init(). + * @param data Pointer to the input data. + * When @a databitLen is not a multiple of 8, the last bits of data must be + * in the most significant bits of the last byte. + * @param databitLen The number of input bits provided in the input data. + * @pre In the previous call to Absorb(), databitLen was a multiple of 8. + * @return SUCCESS if successful, FAIL otherwise. + */ +HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen); +/** + * Function to squeeze output data from the sponge function. + * If @a hashbitlen was not 0 in the call to Init(), the number of output bits is equal to @a hashbitlen. + * If @a hashbitlen was 0 in the call to Init(), the output bits must be extracted using the Squeeze() function. + * @param state Pointer to the state of the sponge function initialized by Init(). + * @param hashval Pointer to the buffer where to store the output data. + * @return SUCCESS if successful, FAIL otherwise. + */ +HashReturn Final(hashState *state, BitSequence *hashval); +/** + * Function to compute a hash using the Keccak[r, c] sponge function. + * The rate r and capacity c values are determined from @a hashbitlen. + * @param hashbitlen The desired number of output bits. + * @param data Pointer to the input data. + * When @a databitLen is not a multiple of 8, the last bits of data must be + * in the most significant bits of the last byte. + * @param databitLen The number of input bits provided in the input data. + * @param hashval Pointer to the buffer where to store the output data. + * @pre The value of hashbitlen must be one of 224, 256, 384 and 512. + * @return SUCCESS if successful, BAD_HASHLEN if the value of hashbitlen is incorrect. + */ +HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval); + +#endif + + +// ================================================================================ +// =================== KeccakNISTInterface.c +// ================================================================================ + + + +/* +The Keccak sponge function, designed by Guido Bertoni, Joan Daemen, +Michaël Peeters and Gilles Van Assche. For more information, feedback or +questions, please refer to our website: http://keccak.noekeon.org/ + +Implementation by the designers, +hereby denoted as "the implementer". + +To the extent possible under law, the implementer has waived all copyright +and related or neighboring rights to the source code in this file. +http://creativecommons.org/publicdomain/zero/1.0/ +*/ + +#include +//#include "KeccakNISTInterface.h" +//#include "KeccakF-1600-interface.h" + +HashReturn Init(hashState *state, int hashbitlen) +{ + switch(hashbitlen) { + case 0: // Default parameters, arbitrary length output + InitSponge((spongeState*)state, 1024, 576); + break; + case 224: + InitSponge((spongeState*)state, 1152, 448); + break; + case 256: + InitSponge((spongeState*)state, 1088, 512); + break; + case 384: + InitSponge((spongeState*)state, 832, 768); + break; + case 512: + InitSponge((spongeState*)state, 576, 1024); + break; + default: + return BAD_HASHLEN; + } + state->fixedOutputLength = hashbitlen; + return SUCCESS; +} + +HashReturn Update(hashState *state, const BitSequence *data, DataLength databitlen) +{ + if ((databitlen % 8) == 0) + return (HashReturn)Absorb((spongeState*)state, data, databitlen); + else { + HashReturn ret = (HashReturn)Absorb((spongeState*)state, data, databitlen - (databitlen % 8)); + if (ret == SUCCESS) { + unsigned char lastByte; + // Align the last partial byte to the least significant bits + lastByte = data[databitlen/8] >> (8 - (databitlen % 8)); + return (HashReturn)Absorb((spongeState*)state, &lastByte, databitlen % 8); + } + else + return ret; + } +} + +HashReturn Final(hashState *state, BitSequence *hashval) +{ + return (HashReturn)Squeeze(state, hashval, state->fixedOutputLength); +} + +HashReturn Hash(int hashbitlen, const BitSequence *data, DataLength databitlen, BitSequence *hashval) +{ + hashState state; + HashReturn result; + + if ((hashbitlen != 224) && (hashbitlen != 256) && (hashbitlen != 384) && (hashbitlen != 512)) + return BAD_HASHLEN; // Only the four fixed output lengths available through this API + result = Init(&state, hashbitlen); + if (result != SUCCESS) + return result; + result = Update(&state, data, databitlen); + if (result != SUCCESS) + return result; + result = Final(&state, hashval); + return result; +} + + +} // end of namespace KeccakImpl +} // end of namespace MUtils + diff --git a/src/KeccakHash.cpp b/src/KeccakHash.cpp new file mode 100644 index 0000000..1023a05 --- /dev/null +++ b/src/KeccakHash.cpp @@ -0,0 +1,210 @@ +/////////////////////////////////////////////////////////////////////////////// +// MuldeR's Utilities for Qt +// Copyright (C) 2004-2014 LoRd_MuldeR +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// +// http://www.gnu.org/licenses/lgpl-2.1.txt +////////////////////////////////////////////////////////////////////////////////// + +/*************************************************************************** +** ** +** MUtils::KeccakHash, an API wrapper bringing the optimized implementation of ** +** Keccak (http://keccak.noekeon.org/) to Qt. ** +** Copyright (C) 2013 Emanuel Eichhammer ** +** ** +** This program is free software: you can redistribute it and/or modify ** +** it under the terms of the GNU General Public License as published by ** +** the Free Software Foundation, either version 3 of the License, or ** +** (at your option) any later version. ** +** ** +** This program is distributed in the hope that it will be useful, ** +** but WITHOUT ANY WARRANTY; without even the implied warranty of ** +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** +** GNU General Public License for more details. ** +** ** +** You should have received a copy of the GNU General Public License ** +** along with this program. If not, see http://www.gnu.org/licenses/. ** +** ** +**************************************************************************** +** Author: Emanuel Eichhammer ** +** Website/Contact: http://www.WorksLikeClockwork.com/ ** +** Date: 12.01.12 ** +****************************************************************************/ + +#include +#include + +#include "3rd_party/keccak_impl.h" + +MUtils::KeccakHash::KeccakHash() +{ + m_initialized = false; + m_state = (MUtils::KeccakImpl::hashState*) _aligned_malloc(sizeof(MUtils::KeccakImpl::hashState), 32); + if(!m_state) + { + throw "[MUtils::KeccakHash] Error: _aligned_malloc() has failed, probably out of heap space!"; + } + memset(m_state, 0, sizeof(MUtils::KeccakImpl::hashState)); + m_hashResult.clear(); +} + +MUtils::KeccakHash::~KeccakHash() +{ + m_hashResult.clear(); + + if(m_state) + { + _aligned_free(m_state); + m_state = NULL; + } +} + +bool MUtils::KeccakHash::init(HashBits hashBits) +{ + if(m_initialized) + { + qWarning("MUtils::KeccakHash has already been initialized!"); + return false; + } + + m_hashResult.clear(); + memset(m_state, 0, sizeof(MUtils::KeccakImpl::hashState)); + int hashBitLength = 0; + + switch (hashBits) + { + case hb224: hashBitLength = 224; break; + case hb256: hashBitLength = 256; break; + case hb384: hashBitLength = 384; break; + case hb512: hashBitLength = 512; break; + default: throw "Invalid hash length!!"; + } + + if(MUtils::KeccakImpl::Init(m_state, hashBitLength) != MUtils::KeccakImpl::SUCCESS) + { + qWarning("KeccakImpl::Init() has failed unexpectedly!"); + return false; + } + + m_hashResult.fill(char(0), hashBitLength/8); + m_initialized = true; + + return true; +} + +bool MUtils::KeccakHash::addData(const QByteArray &data) +{ + return addData(data.constData(), data.size()); +} + +bool MUtils::KeccakHash::addData(const char *data, int size) +{ + if(!m_initialized) + { + qWarning("MUtils::KeccakHash has not been initialized yet!"); + return false; + } + + if(MUtils::KeccakImpl::Update(m_state, (MUtils::KeccakImpl::BitSequence*)data, size*8) != MUtils::KeccakImpl::SUCCESS) + { + qWarning("KeccakImpl::Update() has failed unexpectedly!"); + m_hashResult.clear(); + m_initialized = false; + return false; + } + + return true; +} + +const QByteArray &MUtils::KeccakHash::finalize() +{ + if(!m_initialized) + { + qWarning("MUtils::KeccakHash has not been initialized yet!"); + m_hashResult.clear(); + return m_hashResult; + } + + if(MUtils::KeccakImpl::Final(m_state, (MUtils::KeccakImpl::BitSequence*)m_hashResult.data()) != MUtils::KeccakImpl::SUCCESS) + { + qWarning("KeccakImpl::Final() has failed unexpectedly!"); + m_hashResult.clear(); + } + + m_initialized = false; + return m_hashResult; +} + +bool MUtils::KeccakHash::selfTest(void) +{ + MUtils::KeccakHash hash; + const QByteArray input("The quick brown fox jumps over the lazy dog"); + bool passed[4] = {false, false, false, false}; + + if(hash.init(MUtils::KeccakHash::hb224)) + { + if(hash.addData(input)) + { + QByteArray result = hash.finalize(); + if(!result.isEmpty()) + { + passed[0] = (_stricmp(result.toHex().constData(), "310aee6b30c47350576ac2873fa89fd190cdc488442f3ef654cf23fe") == 0); + if(!passed[0]) qWarning("MUtils::KeccakHash self-test: Test #1 failed !!!"); + } + } + } + + if(hash.init(MUtils::KeccakHash::hb256)) + { + if(hash.addData(input)) + { + QByteArray result = hash.finalize(); + if(!result.isEmpty()) + { + passed[1] = (_stricmp(result.toHex().constData(), "4d741b6f1eb29cb2a9b9911c82f56fa8d73b04959d3d9d222895df6c0b28aa15") == 0); + if(!passed[1]) qWarning("MUtils::KeccakHash self-test: Test #2 failed !!!"); + } + } + } + + if(hash.init(MUtils::KeccakHash::hb384)) + { + if(hash.addData(input)) + { + QByteArray result = hash.finalize(); + if(!result.isEmpty()) + { + passed[2] = (_stricmp(result.toHex().constData(), "283990fa9d5fb731d786c5bbee94ea4db4910f18c62c03d173fc0a5e494422e8a0b3da7574dae7fa0baf005e504063b3") == 0); + if(!passed[2]) qWarning("MUtils::KeccakHash self-test: Test #3 failed !!!"); + } + } + } + + if(hash.init(MUtils::KeccakHash::hb512)) + { + if(hash.addData(input)) + { + QByteArray result = hash.finalize(); + if(!result.isEmpty()) + { + passed[3] = (_stricmp(result.toHex().constData(), "d135bb84d0439dbac432247ee573a23ea7d3c9deb2a968eb31d47c4fb45f1ef4422d6c531b5b9bd6f449ebcc449ea94d0a8f05f62130fda612da53c79659f609") == 0); + if(!passed[3]) qWarning("MUtils::KeccakHash self-test: Test #4 failed !!!"); + } + } + } + + return (passed[0] && passed[1] && passed[2] && passed[3]); +} diff --git a/src/Version.cpp b/src/Version.cpp index b55e528..a5a40b5 100644 --- a/src/Version.cpp +++ b/src/Version.cpp @@ -26,6 +26,10 @@ #include #include +#ifdef _MSC_VER +#define _snscanf(X, Y, Z, ...) _snscanf_s((X), (Y), (Z), __VA_ARGS__) +#endif + /////////////////////////////////////////////////////////////////////////////// static const char *g_months_lut[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; @@ -46,31 +50,18 @@ static int month2int(const char *str) return ret; } -const QDate MUtils::Version::build_date(const char *const raw_date) +const QDate MUtils::Version::build_date(const char *const date_str) { + bool ok = true; int date[3] = {0, 0, 0}; - char temp_m[4], temp_d[3], temp_y[5]; + char month_s[4]; - temp_m[0] = raw_date[0x0]; - temp_m[1] = raw_date[0x1]; - temp_m[2] = raw_date[0x2]; - temp_m[3] = 0x00; + ok = ok && (_snscanf(&date_str[0x0], 3, "%s", &month_s) == 1); + ok = ok && ((date[1] = month2int(month_s)) > 0); + ok = ok && (_snscanf(&date_str[0x4], 2, "%d", &date[0]) == 1); + ok = ok && (_snscanf(&date_str[0x7], 4, "%d", &date[2]) == 1); - temp_d[0] = raw_date[0x4]; - temp_d[1] = raw_date[0x5]; - temp_d[2] = 0x00; - - temp_y[0] = raw_date[0x7]; - temp_y[1] = raw_date[0x8]; - temp_y[2] = raw_date[0x9]; - temp_y[3] = raw_date[0xA]; - temp_y[4] = 0x00; - - date[0] = atoi(temp_y); - date[1] = month2int(temp_m); - date[2] = atoi(temp_d); - - if(!((date[0] > 0) && (date[1] > 0) && (date[2] > 0))) + if(!ok) { MUTILS_THROW("Internal error: Date format could not be recognized!"); } @@ -78,4 +69,21 @@ const QDate MUtils::Version::build_date(const char *const raw_date) return QDate(date[0], date[1], date[2]); } +static const QTime build_time(const char *const time_str) +{ + bool ok = true; + int time[3] = {0, 0, 0}; + + ok = ok && (_snscanf(&time_str[0x0], 2, "%d", &time[0]) == 1); + ok = ok && (_snscanf(&time_str[0x3], 2, "%d", &time[1]) == 1); + ok = ok && (_snscanf(&time_str[0x6], 2, "%d", &time[2]) == 1); + + if(!ok) + { + MUTILS_THROW("Internal error: Time format could not be recognized!"); + } + + return QTime(time[0], time[1], time[2]); +} + ///////////////////////////////////////////////////////////////////////////////