diff options
-rw-r--r-- | GNUmakefile | 2 | ||||
-rw-r--r-- | License.txt | 1 | ||||
-rw-r--r-- | TestVectors/all.txt | 4 | ||||
-rw-r--r-- | argnames.h | 6 | ||||
-rw-r--r-- | basecode.cpp | 3 | ||||
-rw-r--r-- | bench.cpp | 17 | ||||
-rw-r--r-- | channels.cpp | 189 | ||||
-rw-r--r-- | channels.h | 48 | ||||
-rw-r--r-- | cryptest.cpp | 5 | ||||
-rw-r--r-- | cryptest.dsp | 26 | ||||
-rw-r--r-- | cryptlib.dsp | 34 | ||||
-rw-r--r-- | files.cpp | 21 | ||||
-rw-r--r-- | files.h | 14 | ||||
-rw-r--r-- | filters.cpp | 4 | ||||
-rw-r--r-- | filters.h | 43 | ||||
-rw-r--r-- | fipsalgt.cpp | 877 | ||||
-rw-r--r-- | fipstest.cpp | 42 | ||||
-rw-r--r-- | md2.cpp | 13 | ||||
-rw-r--r-- | misc.h | 65 | ||||
-rw-r--r-- | regtest.cpp | 9 | ||||
-rw-r--r-- | ripemd.cpp | 610 | ||||
-rw-r--r-- | ripemd.h | 39 | ||||
-rw-r--r-- | rng.cpp | 22 | ||||
-rw-r--r-- | rng.h | 5 | ||||
-rw-r--r-- | test.cpp | 15 | ||||
-rw-r--r-- | usage.dat | 6 | ||||
-rw-r--r-- | validat1.cpp | 34 | ||||
-rw-r--r-- | validat3.cpp | 198 | ||||
-rw-r--r-- | validate.h | 4 |
29 files changed, 2185 insertions, 171 deletions
diff --git a/GNUmakefile b/GNUmakefile index 942f7bd..39f841f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -44,7 +44,7 @@ endif OBJS = $(SRCS:.cpp=.o) # test.o needs to be after bench.o for cygwin 1.1.4 (possible ld bug?) -TESTOBJS = bench.o test.o validat1.o validat2.o validat3.o adhoc.o datatest.o regtest.o +TESTOBJS = bench.o test.o validat1.o validat2.o validat3.o adhoc.o datatest.o regtest.o fipsalgt.o LIBOBJS = $(filter-out $(TESTOBJS),$(OBJS)) all: cryptest.exe diff --git a/License.txt b/License.txt index 2a8ec4e..fb48551 100644 --- a/License.txt +++ b/License.txt @@ -26,6 +26,7 @@ Chris Morgan - rijndael.cpp Paulo Baretto - rijndael.cpp, skipjack.cpp, square.cpp Richard De Moliner - safer.cpp Matthew Skala - twofish.cpp +Kevin Springle - camellia.cpp, shacal2.cpp, ttmac.cpp, whrlpool.cpp, ripemd.cpp Permission to use, copy, modify, and distribute this compilation for any purpose, including commercial applications, is hereby granted diff --git a/TestVectors/all.txt b/TestVectors/all.txt index 62d4479..64bd7f3 100644 --- a/TestVectors/all.txt +++ b/TestVectors/all.txt @@ -1,5 +1,9 @@ AlgorithmType: FileList Name: all.txt collection +Test: camelia.txt +Test: shacal2.txt +Test: ttmac.txt +Test: whrlpool.txt Test: dlies.txt Test: dsa.txt Test: dsa_1363.txt @@ -46,6 +46,12 @@ CRYPTOPP_DEFINE_NAME_STRING(SignatureVerificationFilterFlags) //!< word32 CRYPTOPP_DEFINE_NAME_STRING(InputBuffer) //!< ConstByteArrayParameter CRYPTOPP_DEFINE_NAME_STRING(OutputBuffer) //!< ByteArrayParameter CRYPTOPP_DEFINE_NAME_STRING(XMACC_Counter) //!< word32 +CRYPTOPP_DEFINE_NAME_STRING(InputFileName) //!< const char * +CRYPTOPP_DEFINE_NAME_STRING(InputStreamPointer) //!< std::istream * +CRYPTOPP_DEFINE_NAME_STRING(InputBinaryMode) //!< bool +CRYPTOPP_DEFINE_NAME_STRING(OutputFileName) //!< const char * +CRYPTOPP_DEFINE_NAME_STRING(OutputStreamPointer) //!< std::ostream * +CRYPTOPP_DEFINE_NAME_STRING(OutputBinaryMode) //!< bool DOCUMENTED_NAMESPACE_END diff --git a/basecode.cpp b/basecode.cpp index 1e81ece..8fe41be 100644 --- a/basecode.cpp +++ b/basecode.cpp @@ -221,7 +221,10 @@ unsigned int Grouper::Put2(const byte *begin, unsigned int length, int messageEn FILTER_OUTPUT(3, begin, length, 0); if (messageEnd) + { FILTER_OUTPUT(4, m_terminator, m_terminator.size(), messageEnd); + m_counter = 0; + } FILTER_END_NO_MESSAGE_END } @@ -12,6 +12,7 @@ #include "tiger.h" #include "ripemd.h" #include "panama.h" +#include "whrlpool.h" #include "idea.h" #include "des.h" #include "rc2.h" @@ -33,10 +34,13 @@ #include "rijndael.h" #include "twofish.h" #include "serpent.h" +#include "shacal2.h" +#include "camellia.h" #include "hmac.h" #include "xormac.h" #include "cbcmac.h" #include "dmac.h" +#include "ttmac.h" #include "blumshub.h" #include "rsa.h" #include "nr.h" @@ -438,7 +442,9 @@ void BenchMarkAll(double t) BenchMarkKeyless<MD5>("MD5", t); BenchMarkKeyless<SHA>("SHA-1", t); BenchMarkKeyless<SHA256>("SHA-256", t); +#ifdef WORD64_AVAILABLE BenchMarkKeyless<SHA512>("SHA-512", t); +#endif BenchMarkKeyless<HAVAL3>("HAVAL (pass=3)", t); BenchMarkKeyless<HAVAL4>("HAVAL (pass=4)", t); BenchMarkKeyless<HAVAL5>("HAVAL (pass=5)", t); @@ -448,6 +454,9 @@ void BenchMarkAll(double t) BenchMarkKeyless<RIPEMD160>("RIPE-MD160", t); BenchMarkKeyless<PanamaHash<LittleEndian> >("Panama Hash (little endian)", t); BenchMarkKeyless<PanamaHash<BigEndian> >("Panama Hash (big endian)", t); +#ifdef WORD64_AVAILABLE + BenchMarkKeyless<Whirlpool>("Whirlpool", t); +#endif BenchMarkKeyed<MDC<MD5>::Encryption>("MDC/MD5", t); BenchMarkKeyed<LR<MD5>::Encryption>("Luby-Rackoff/MD5", t); BenchMarkKeyed<DES::Encryption>("DES", t); @@ -490,9 +499,17 @@ void BenchMarkAll(double t) BenchMarkKeyed<WAKE_OFB<LittleEndian>::Encryption>("WAKE-OFB-LE", t); BenchMarkKeyed<PanamaCipher<LittleEndian>::Encryption>("Panama Cipher (little endian)", t); BenchMarkKeyed<PanamaCipher<BigEndian>::Encryption>("Panama Cipher (big endian)", t); + BenchMarkKeyedVariable<SHACAL2::Encryption>("SHACAL-2 (128-bit key)", t, 16); + BenchMarkKeyedVariable<SHACAL2::Encryption>("SHACAL-2 (512-bit key)", t, 64); +#ifdef WORD64_AVAILABLE + BenchMarkKeyedVariable<Camellia::Encryption>("Camellia (128-bit key)", t, 16); + BenchMarkKeyedVariable<Camellia::Encryption>("Camellia (192-bit key)", t, 24); + BenchMarkKeyedVariable<Camellia::Encryption>("Camellia (256-bit key)", t, 32); +#endif BenchMarkKeyed<MD5MAC>("MD5-MAC", t); BenchMarkKeyed<XMACC<MD5> >("XMACC/MD5", t); BenchMarkKeyed<HMAC<MD5> >("HMAC/MD5", t); + BenchMarkKeyed<TTMAC>("Two-Track-MAC", t); BenchMarkKeyed<CBC_MAC<Rijndael> >("CBC-MAC/Rijndael", t); BenchMarkKeyed<DMAC<Rijndael> >("DMAC/Rijndael", t); diff --git a/channels.cpp b/channels.cpp index d13bcf4..7bb31dd 100644 --- a/channels.cpp +++ b/channels.cpp @@ -85,73 +85,82 @@ void MessageSwitch::MessageSeriesEnd(int propagation=-1); */ #endif -class ChannelRouteIterator -{ -public: - typedef ChannelSwitch::RouteMap::const_iterator MapIterator; - typedef ChannelSwitch::DefaultRouteList::const_iterator ListIterator; - const std::string m_channel; - bool m_useDefault; - MapIterator m_itMapCurrent, m_itMapEnd; - ListIterator m_itListCurrent, m_itListEnd; +// +// ChannelRouteIterator +////////////////////////// - ChannelRouteIterator(ChannelSwitch &cs, const std::string &channel) - : m_channel(channel) +void ChannelRouteIterator::Reset(const std::string &channel) +{ + m_channel = channel; + pair<MapIterator, MapIterator> range = m_cs.m_routeMap.equal_range(channel); + if (range.first == range.second) { - pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel); - if (range.first == range.second) - { - m_useDefault = true; - m_itListCurrent = cs.m_defaultRoutes.begin(); - m_itListEnd = cs.m_defaultRoutes.end(); - } - else - { - m_useDefault = false; - m_itMapCurrent = range.first; - m_itMapEnd = range.second; - } + m_useDefault = true; + m_itListCurrent = m_cs.m_defaultRoutes.begin(); + m_itListEnd = m_cs.m_defaultRoutes.end(); } - - bool End() const + else { - return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd; + m_useDefault = false; + m_itMapCurrent = range.first; + m_itMapEnd = range.second; } +} - void Next() - { - if (m_useDefault) - ++m_itListCurrent; - else - ++m_itMapCurrent; - } +bool ChannelRouteIterator::End() const +{ + return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd; +} - BufferedTransformation & Destination() - { - return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first; - } +void ChannelRouteIterator::Next() +{ + if (m_useDefault) + ++m_itListCurrent; + else + ++m_itMapCurrent; +} - const std::string & Channel() - { - if (m_useDefault) - return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel; - else - return m_itMapCurrent->second.second; - } -}; +BufferedTransformation & ChannelRouteIterator::Destination() +{ + return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first; +} + +const std::string & ChannelRouteIterator::Channel() +{ + if (m_useDefault) + return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel; + else + return m_itMapCurrent->second.second; +} + + +// +// ChannelSwitch +/////////////////// unsigned int ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking) { - if (!blocking) - throw BlockingInputOnly("ChannelSwitch"); + if (m_blocked) + { + m_blocked = false; + goto WasBlocked; + } - ChannelRouteIterator it(*this, channel); - while (!it.End()) + m_it.Reset(channel); + + while (!m_it.End()) { - it.Destination().ChannelPut2(it.Channel(), begin, length, messageEnd, blocking); - it.Next(); + WasBlocked: + if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking)) + { + m_blocked = true; + return 1; + } + + m_it.Next(); } + return 0; } @@ -163,51 +172,74 @@ void ChannelSwitch::ChannelInitialize(const std::string &channel, const NameValu m_defaultRoutes.clear(); } - ChannelRouteIterator it(*this, channel); - while (!it.End()) + m_it.Reset(channel); + + while (!m_it.End()) { - it.Destination().ChannelInitialize(it.Channel(), parameters, propagation); - it.Next(); + m_it.Destination().ChannelInitialize(m_it.Channel(), parameters, propagation); + m_it.Next(); } } bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking) { - if (!blocking) - throw BlockingInputOnly("ChannelSwitch"); + if (m_blocked) + { + m_blocked = false; + goto WasBlocked; + } - ChannelRouteIterator it(*this, channel); - while (!it.End()) + m_it.Reset(channel); + + while (!m_it.End()) { - it.Destination().ChannelFlush(it.Channel(), completeFlush, propagation, blocking); - it.Next(); + WasBlocked: + if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking)) + { + m_blocked = true; + return true; + } + + m_it.Next(); } + return false; } bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) { - if (!blocking) - throw BlockingInputOnly("ChannelSwitch"); + if (m_blocked) + { + m_blocked = false; + goto WasBlocked; + } - ChannelRouteIterator it(*this, channel); - while (!it.End()) + m_it.Reset(channel); + + while (!m_it.End()) { - it.Destination().ChannelMessageSeriesEnd(it.Channel(), propagation); - it.Next(); + WasBlocked: + if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation)) + { + m_blocked = true; + return true; + } + + m_it.Next(); } + return false; } byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, unsigned int &size) { - ChannelRouteIterator it(*this, channel); - if (!it.End()) + m_it.Reset(channel); + if (!m_it.End()) { - BufferedTransformation &target = it.Destination(); - it.Next(); - if (it.End()) // there is only one target channel - return target.ChannelCreatePutSpace(it.Channel(), size); + BufferedTransformation &target = m_it.Destination(); + m_it.Next(); + if (m_it.End()) // there is only one target channel + return target.ChannelCreatePutSpace(m_it.Channel(), size); } size = 0; return NULL; @@ -215,10 +247,9 @@ byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, unsigned unsigned int ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, unsigned int length, int messageEnd, bool blocking) { - if (!blocking) - throw BlockingInputOnly("ChannelSwitch"); + ChannelRouteIterator it(*this); + it.Reset(channel); - ChannelRouteIterator it(*this, channel); if (!it.End()) { BufferedTransformation &target = it.Destination(); @@ -227,8 +258,8 @@ unsigned int ChannelSwitch::ChannelPutModifiable2(const std::string &channel, by if (it.End()) // there is only one target channel return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking); } - ChannelPut2(channel, inString, length, messageEnd, blocking); - return false; + + return ChannelPut2(channel, inString, length, messageEnd, blocking); } void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination) @@ -44,16 +44,48 @@ private: }; #endif +class ChannelSwitchTypedefs +{ +public: + typedef std::pair<BufferedTransformation *, std::string> Route; + typedef std::multimap<std::string, Route> RouteMap; + + typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute; + typedef std::list<DefaultRoute> DefaultRouteList; + + typedef RouteMap::const_iterator MapIterator; + typedef DefaultRouteList::const_iterator ListIterator; +}; + +class ChannelSwitch; + +class ChannelRouteIterator : public ChannelSwitchTypedefs +{ +public: + ChannelSwitch& m_cs; + std::string m_channel; + bool m_useDefault; + MapIterator m_itMapCurrent, m_itMapEnd; + ListIterator m_itListCurrent, m_itListEnd; + + ChannelRouteIterator(ChannelSwitch &cs) : m_cs(cs) {} + void Reset(const std::string &channel); + bool End() const; + void Next(); + BufferedTransformation & Destination(); + const std::string & Channel(); +}; + //! Route input to different and/or multiple channels based on channel ID -class ChannelSwitch : public Multichannel<Sink> +class ChannelSwitch : public Multichannel<Sink>, public ChannelSwitchTypedefs { public: - ChannelSwitch() {} - ChannelSwitch(BufferedTransformation &destination) + ChannelSwitch() : m_it(*this), m_blocked(false) {} + ChannelSwitch(BufferedTransformation &destination) : m_it(*this), m_blocked(false) { AddDefaultRoute(destination); } - ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) + ChannelSwitch(BufferedTransformation &destination, const std::string &outChannel) : m_it(*this), m_blocked(false) { AddDefaultRoute(destination, outChannel); } @@ -75,14 +107,12 @@ public: void RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel); private: - typedef std::pair<BufferedTransformation *, std::string> Route; - typedef std::multimap<std::string, Route> RouteMap; RouteMap m_routeMap; - - typedef std::pair<BufferedTransformation *, value_ptr<std::string> > DefaultRoute; - typedef std::list<DefaultRoute> DefaultRouteList; DefaultRouteList m_defaultRoutes; + ChannelRouteIterator m_it; + bool m_blocked; + friend class ChannelRouteIterator; }; diff --git a/cryptest.cpp b/cryptest.cpp index 5302331..9aea0ba 100644 --- a/cryptest.cpp +++ b/cryptest.cpp @@ -14,6 +14,7 @@ USEUNIT("bfinit.cpp"); USEUNIT("blowfish.cpp"); USEUNIT("blumgold.cpp"); USEUNIT("blumshub.cpp"); +USEUNIT("camellia.cpp"); USEUNIT("cast.cpp"); USEUNIT("cast128s.cpp"); USEUNIT("crc.cpp"); @@ -62,11 +63,11 @@ USEUNIT("ripemd.cpp"); USEUNIT("rng.cpp"); USEUNIT("rsa.cpp"); USEUNIT("safer.cpp"); -USEUNIT("sapphire.cpp"); USEUNIT("seal.cpp"); USEUNIT("secshare.cpp"); USEUNIT("secsplit.cpp"); USEUNIT("sha.cpp"); +USEUNIT("shacal2.cpp"); USEUNIT("shark.cpp"); USEUNIT("sharkbox.cpp"); USEUNIT("square.cpp"); @@ -75,10 +76,12 @@ USEUNIT("tea.cpp"); USEUNIT("test.cpp"); USEUNIT("tiger.cpp"); USEUNIT("tigertab.cpp"); +USEUNIT("ttmac.cpp"); USEUNIT("validat1.cpp"); USEUNIT("validat2.cpp"); USEUNIT("validat3.cpp"); USEUNIT("wake.cpp"); +USEUNIT("whrlpool.cpp"); USEUNIT("zbits.cpp"); USEUNIT("zdeflate.cpp"); USEUNIT("zinflate.cpp"); diff --git a/cryptest.dsp b/cryptest.dsp index 74e0dc1..f7fb19e 100644 --- a/cryptest.dsp +++ b/cryptest.dsp @@ -1,5 +1,5 @@ # Microsoft Developer Studio Project File - Name="cryptest" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 60000 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Console Application" 0x0103 @@ -74,7 +74,7 @@ PostBuild_Cmds=echo This configuration is used to build a static binary for FIPS # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c -# ADD CPP /nologo /G5 /Gz /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm200 /c +# ADD CPP /nologo /G5 /Gz /MTd /W3 /GX /ZI /Od /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /D "WIN32" /YX /FD /Zm300 /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -126,7 +126,7 @@ LINK32=link.exe # PROP Ignore_Export_Lib 0 # PROP Target_Dir "" # ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c -# ADD CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm200 /c +# ADD CPP /nologo /MTd /W3 /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /Zm300 /c # ADD BASE RSC /l 0x409 /d "_DEBUG" # ADD RSC /l 0x409 /d "_DEBUG" BSC32=bscmake.exe @@ -157,6 +157,14 @@ SOURCE=.\3wayval.dat # End Source File # Begin Source File +SOURCE=.\anubisv.dat +# End Source File +# Begin Source File + +SOURCE=.\camellia.dat +# End Source File +# Begin Source File + SOURCE=.\cast128v.dat # End Source File # Begin Source File @@ -225,6 +233,10 @@ SOURCE=.\ideaval.dat # End Source File # Begin Source File +SOURCE=.\khazadv.dat +# End Source File +# Begin Source File + SOURCE=.\luc1024.dat # End Source File # Begin Source File @@ -337,6 +349,14 @@ SOURCE=.\serpentv.dat # End Source File # Begin Source File +SOURCE=.\shacal1v.dat +# End Source File +# Begin Source File + +SOURCE=.\shacal2v.dat +# End Source File +# Begin Source File + SOURCE=.\sharkval.dat # End Source File # Begin Source File diff --git a/cryptlib.dsp b/cryptlib.dsp index bbf78d3..1c32dd0 100644 --- a/cryptlib.dsp +++ b/cryptlib.dsp @@ -1,5 +1,5 @@ # Microsoft Developer Studio Project File - Name="cryptlib" - Package Owner=<4> -# Microsoft Developer Studio Generated Build File, Format Version 60000 +# Microsoft Developer Studio Generated Build File, Format Version 6.00 # ** DO NOT EDIT ** # TARGTYPE "Win32 (x86) Static Library" 0x0104 @@ -230,6 +230,10 @@ SOURCE=.\blumshub.cpp # End Source File # Begin Source File +SOURCE=.\camellia.cpp +# End Source File +# Begin Source File + SOURCE=.\cast.cpp # End Source File # Begin Source File @@ -527,6 +531,10 @@ SOURCE=.\sha.cpp # End Source File # Begin Source File +SOURCE=.\shacal2.cpp +# End Source File +# Begin Source File + SOURCE=.\shark.cpp # End Source File # Begin Source File @@ -579,6 +587,10 @@ SOURCE=.\trdlocal.cpp # End Source File # Begin Source File +SOURCE=.\ttmac.cpp +# End Source File +# Begin Source File + SOURCE=.\twofish.cpp # End Source File # Begin Source File @@ -591,6 +603,10 @@ SOURCE=.\wake.cpp # End Source File # Begin Source File +SOURCE=.\whrlpool.cpp +# End Source File +# Begin Source File + SOURCE=.\winpipes.cpp # End Source File # Begin Source File @@ -667,6 +683,10 @@ SOURCE=.\blumshub.h # End Source File # Begin Source File +SOURCE=.\camellia.h +# End Source File +# Begin Source File + SOURCE=.\cast.h # End Source File # Begin Source File @@ -991,6 +1011,10 @@ SOURCE=.\sha.h # End Source File # Begin Source File +SOURCE=.\shacal2.h +# End Source File +# Begin Source File + SOURCE=.\shark.h # End Source File # Begin Source File @@ -1035,6 +1059,10 @@ SOURCE=.\trunhash.h # End Source File # Begin Source File +SOURCE=.\ttmac.h +# End Source File +# Begin Source File + SOURCE=.\twofish.h # End Source File # Begin Source File @@ -1047,6 +1075,10 @@ SOURCE=.\wake.h # End Source File # Begin Source File +SOURCE=.\whrlpool.h +# End Source File +# Begin Source File + SOURCE=.\winpipes.h # End Source File # Begin Source File @@ -16,10 +16,12 @@ void Files_TestInstantiations() void FileStore::StoreInitialize(const NameValuePairs ¶meters) { + m_file.close(); + m_file.clear(); const char *fileName; - if (parameters.GetValue("InputFileName", fileName)) + if (parameters.GetValue(Name::InputFileName(), fileName)) { - ios::openmode binary = parameters.GetValueWithDefault("InputBinaryMode", true) ? ios::binary : ios::openmode(0); + ios::openmode binary = parameters.GetValueWithDefault(Name::InputBinaryMode(), true) ? ios::binary : ios::openmode(0); m_file.open(fileName, ios::in | binary); if (!m_file) throw OpenErr(fileName); @@ -28,7 +30,7 @@ void FileStore::StoreInitialize(const NameValuePairs ¶meters) else { m_stream = NULL; - parameters.GetValue("InputStreamPointer", m_stream); + parameters.GetValue(Name::InputStreamPointer(), m_stream); } m_waiting = false; } @@ -137,12 +139,19 @@ unsigned int FileStore::CopyRangeTo2(BufferedTransformation &target, unsigned lo return 0; } +unsigned long FileStore::Skip(unsigned long skipMax) +{ + unsigned long oldPos = m_stream->tellg(); + m_stream->seekg(skipMax, ios_base::cur); + return (unsigned long)m_stream->tellg() - oldPos; +} + void FileSink::IsolatedInitialize(const NameValuePairs ¶meters) { const char *fileName; - if (parameters.GetValue("OutputFileName", fileName)) + if (parameters.GetValue(Name::OutputFileName(), fileName)) { - ios::openmode binary = parameters.GetValueWithDefault("OutputBinaryMode", true) ? ios::binary : ios::openmode(0); + ios::openmode binary = parameters.GetValueWithDefault(Name::OutputBinaryMode(), true) ? ios::binary : ios::openmode(0); m_file.open(fileName, ios::out | ios::trunc | binary); if (!m_file) throw OpenErr(fileName); @@ -151,7 +160,7 @@ void FileSink::IsolatedInitialize(const NameValuePairs ¶meters) else { m_stream = NULL; - parameters.GetValue("OutputStreamPointer", m_stream); + parameters.GetValue(Name::OutputStreamPointer(), m_stream); } } @@ -3,6 +3,7 @@ #include "cryptlib.h" #include "filters.h" +#include "argnames.h" #include <iostream> #include <fstream> @@ -23,15 +24,16 @@ public: FileStore() : m_stream(NULL) {} FileStore(std::istream &in) - {StoreInitialize(MakeParameters("InputStreamPointer", &in));} + {StoreInitialize(MakeParameters(Name::InputStreamPointer(), &in));} FileStore(const char *filename) - {StoreInitialize(MakeParameters("InputFileName", filename));} + {StoreInitialize(MakeParameters(Name::InputFileName(), filename));} std::istream* GetStream() {return m_stream;} unsigned long MaxRetrievable() const; unsigned int TransferTo2(BufferedTransformation &target, unsigned long &transferBytes, const std::string &channel=NULL_CHANNEL, bool blocking=true); unsigned int CopyRangeTo2(BufferedTransformation &target, unsigned long &begin, unsigned long end=ULONG_MAX, const std::string &channel=NULL_CHANNEL, bool blocking=true) const; + unsigned long Skip(unsigned long skipMax=ULONG_MAX); private: void StoreInitialize(const NameValuePairs ¶meters); @@ -54,9 +56,9 @@ public: FileSource(BufferedTransformation *attachment = NULL) : SourceTemplate<FileStore>(attachment) {} FileSource(std::istream &in, bool pumpAll, BufferedTransformation *attachment = NULL) - : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputStreamPointer", &in));} + : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputStreamPointer(), &in));} FileSource(const char *filename, bool pumpAll, BufferedTransformation *attachment = NULL, bool binary=true) - : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters("InputFileName", filename)("InputBinaryMode", binary));} + : SourceTemplate<FileStore>(attachment) {SourceInitialize(pumpAll, MakeParameters(Name::InputFileName(), filename)(Name::InputBinaryMode(), binary));} std::istream* GetStream() {return m_store.GetStream();} }; @@ -75,9 +77,9 @@ public: FileSink() : m_stream(NULL) {} FileSink(std::ostream &out) - {IsolatedInitialize(MakeParameters("OutputStreamPointer", &out));} + {IsolatedInitialize(MakeParameters(Name::OutputStreamPointer(), &out));} FileSink(const char *filename, bool binary=true) - {IsolatedInitialize(MakeParameters("OutputFileName", filename)("OutputBinaryMode", binary));} + {IsolatedInitialize(MakeParameters(Name::OutputFileName(), filename)("OutputBinaryMode", binary));} std::ostream* GetStream() {return m_stream;} diff --git a/filters.cpp b/filters.cpp index 64c2a37..4c4d660 100644 --- a/filters.cpp +++ b/filters.cpp @@ -381,10 +381,10 @@ void Redirector::ChannelInitialize(const std::string &channel, const NameValuePa if (channel.empty()) { m_target = parameters.GetValueWithDefault("RedirectionTargetPointer", (BufferedTransformation*)NULL); - m_passSignal = parameters.GetValueWithDefault("PassSignal", true); + m_behavior = parameters.GetIntValueWithDefault("RedirectionBehavior", PASS_EVERYTHING); } - if (m_target && m_passSignal) + if (m_target && GetPassSignals()) m_target->ChannelInitialize(channel, parameters, propagation); } @@ -366,36 +366,55 @@ typedef SignatureVerificationFilter VerifierFilter; // for backwards compatibili class Redirector : public CustomSignalPropagation<Sink> { public: - Redirector() : m_target(NULL), m_passSignal(true) {} - Redirector(BufferedTransformation &target, bool passSignal=true) : m_target(&target), m_passSignal(passSignal) {} + enum Behavior + { + DATA_ONLY = 0x00, + PASS_SIGNALS = 0x01, + PASS_WAIT_OBJECTS = 0x02, + PASS_EVERYTHING = PASS_SIGNALS | PASS_WAIT_OBJECTS + }; + + Redirector() : m_target(NULL), m_behavior(PASS_EVERYTHING) {} + Redirector(BufferedTransformation &target, Behavior behavior=PASS_EVERYTHING) + : m_target(&target), m_behavior(behavior) {} void Redirect(BufferedTransformation &target) {m_target = ⌖} void StopRedirection() {m_target = NULL;} - bool GetPassSignal() const {return m_passSignal;} - void SetPassSignal(bool passSignal) {m_passSignal = passSignal;} + + Behavior GetBehavior() {return (Behavior) m_behavior;} + void SetBehavior(Behavior behavior) {m_behavior=behavior;} + bool GetPassSignals() const {return (m_behavior & PASS_SIGNALS) != 0;} + void SetPassSignals(bool pass) { if (pass) m_behavior |= PASS_SIGNALS; else m_behavior &= ~(word32) PASS_SIGNALS; } + bool GetPassWaitObjects() const {return (m_behavior & PASS_WAIT_OBJECTS) != 0;} + void SetPassWaitObjects(bool pass) { if (pass) m_behavior |= PASS_WAIT_OBJECTS; else m_behavior &= ~(word32) PASS_WAIT_OBJECTS; } unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_target ? m_target->Put2(begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;} + {return m_target ? m_target->Put2(begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} void Initialize(const NameValuePairs ¶meters, int propagation) {ChannelInitialize(NULL_CHANNEL, parameters, propagation);} bool Flush(bool hardFlush, int propagation=-1, bool blocking=true) - {return m_target && m_passSignal ? m_target->Flush(hardFlush, propagation, blocking) : false;} + {return m_target && GetPassSignals() ? m_target->Flush(hardFlush, propagation, blocking) : false;} bool MessageSeriesEnd(int propagation=-1, bool blocking=true) - {return m_target && m_passSignal ? m_target->MessageSeriesEnd(propagation, blocking) : false;} + {return m_target && GetPassSignals() ? m_target->MessageSeriesEnd(propagation, blocking) : false;} void ChannelInitialize(const std::string &channel, const NameValuePairs ¶meters=g_nullNameValuePairs, int propagation=-1); unsigned int ChannelPut2(const std::string &channel, const byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_target ? m_target->ChannelPut2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;} + {return m_target ? m_target->ChannelPut2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} unsigned int ChannelPutModifiable2(const std::string &channel, byte *begin, unsigned int length, int messageEnd, bool blocking) - {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, m_passSignal ? messageEnd : 0, blocking) : 0;} + {return m_target ? m_target->ChannelPutModifiable2(channel, begin, length, GetPassSignals() ? messageEnd : 0, blocking) : 0;} bool ChannelFlush(const std::string &channel, bool completeFlush, int propagation=-1, bool blocking=true) - {return m_target && m_passSignal ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} + {return m_target && GetPassSignals() ? m_target->ChannelFlush(channel, completeFlush, propagation, blocking) : false;} bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true) - {return m_target && m_passSignal ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} + {return m_target && GetPassSignals() ? m_target->ChannelMessageSeriesEnd(channel, propagation, blocking) : false;} + + unsigned int GetMaxWaitObjectCount() const + { return m_target && GetPassWaitObjects() ? m_target->GetMaxWaitObjectCount() : 0; } + void GetWaitObjects(WaitObjectContainer &container) + { if (m_target && GetPassWaitObjects()) m_target->GetWaitObjects(container); } private: BufferedTransformation *m_target; - bool m_passSignal; + word32 m_behavior; }; // Used By ProxyFilter diff --git a/fipsalgt.cpp b/fipsalgt.cpp new file mode 100644 index 0000000..4537ee4 --- /dev/null +++ b/fipsalgt.cpp @@ -0,0 +1,877 @@ +// fipsalgt.cpp - written and placed in the public domain by Wei Dai + +// This file implements the various algorithm tests needed to pass FIPS 140 validation. +// They're preserved here (commented out) in case Crypto++ needs to be revalidated. + +/* +class LineBreakParser : public AutoSignaling<Bufferless<Filter> > +{ +public: + LineBreakParser(BufferedTransformation *attachment=NULL, byte lineEnd='\n') + : AutoSignaling<Bufferless<Filter> >(attachment), m_lineEnd(lineEnd) {} + + unsigned int Put2(const byte *begin, unsigned int length, int messageEnd, bool blocking) + { + if (!blocking) + throw BlockingInputOnly("LineBreakParser"); + + unsigned int i, last = 0; + for (i=0; i<length; i++) + { + if (begin[i] == m_lineEnd) + { + AttachedTransformation()->Put2(begin+last, i-last, GetAutoSignalPropagation(), blocking); + last = i+1; + } + } + if (last != i) + AttachedTransformation()->Put2(begin+last, i-last, 0, blocking); + + if (messageEnd && GetAutoSignalPropagation()) + { + AttachedTransformation()->MessageEnd(GetAutoSignalPropagation()-1, blocking); + AttachedTransformation()->MessageSeriesEnd(GetAutoSignalPropagation()-1, blocking); + } + + return 0; + } + +private: + byte m_lineEnd; +}; + +class TestDataParser : public Unflushable<FilterWithInputQueue> +{ +public: + enum DataType {OTHER, COUNT, KEY_T, IV, INPUT, OUTPUT}; + + TestDataParser(std::string algorithm, std::string test, std::string mode, unsigned int feedbackSize, bool encrypt, BufferedTransformation *attachment) + : Unflushable<FilterWithInputQueue>(attachment) + , m_algorithm(algorithm), m_test(test), m_mode(mode), m_feedbackSize(feedbackSize) + , m_firstLine(true), m_blankLineTransition(0) + { + m_nameToType["COUNT"] = COUNT; + m_nameToType["KEY"] = KEY_T; + m_nameToType["KEYs"] = KEY_T; + m_nameToType["key"] = KEY_T; + m_nameToType["IV"] = IV; + m_nameToType["IV1"] = IV; + m_nameToType["CV"] = IV; + m_nameToType["CV1"] = IV; + m_nameToType["IB"] = IV; + m_nameToType["TEXT"] = INPUT; + m_nameToType["RESULT"] = OUTPUT; + SetEncrypt(encrypt); + + if (m_algorithm == "DSS") + { + if (m_test == "prime") + m_trigger = "Prime"; + else if (m_test == "pqg") + m_trigger = "N"; + else if (m_test == "xy") + m_trigger = "G"; + else if (m_test == "gensig") + m_trigger = "Msg"; + else if (m_test == "versig") + m_trigger = "Sig"; + else if (m_test == "verpqg") + m_trigger = "c"; + } + } + + void SetEncrypt(bool encrypt) + { + m_encrypt = encrypt; + if (encrypt) + { + m_nameToType["PLAINTEXT"] = INPUT; + m_nameToType["CIPHERTEXT"] = OUTPUT; + m_nameToType["PT"] = INPUT; + m_nameToType["CT"] = OUTPUT; + } + else + { + m_nameToType["PLAINTEXT"] = OUTPUT; + m_nameToType["CIPHERTEXT"] = INPUT; + m_nameToType["PT"] = OUTPUT; + m_nameToType["CT"] = INPUT; + } + } + +protected: + void OutputData(std::string &output, const std::string &key, const std::string &data) + { + output += key; + output += "= "; + output += data; + output += "\n"; + } + + void OutputData(std::string &output, const std::string &key, int data) + { + OutputData(output, key, IntToString(data)); + } + + void OutputData(std::string &output, const std::string &key, const SecByteBlock &data) + { + output += key; + output += "= "; + HexEncoder(new StringSink(output), false).Put(data, data.size()); + output += "\n"; + } + + void OutputData(std::string &output, const std::string &key, const Integer &data) + { + SecByteBlock s(data.MinEncodedSize()); + data.Encode(s, s.size()); + OutputData(output, key, s); + } + + void OutputData(std::string &output, DataType t, const std::string &data) + { + if (m_algorithm == "SKIPJACK") + { + if (m_test == "KAT") + { + if (t == OUTPUT) + output = m_line + data + "\n"; + } + else + { + if (t != COUNT) + { + output += m_typeToName[t]; + output += "="; + } + output += data; + output += t == OUTPUT ? "\n" : " "; + } + } + else if (m_algorithm == "TDES" && t == KEY_T && m_typeToName[KEY_T].empty()) + { + output += "KEY1 = "; + output += data.substr(0, 16); + output += "\nKEY2 = "; + output += data.size() > 16 ? data.substr(16, 16) : data.substr(0, 16); + output += "\nKEY3 = "; + output += data.size() > 32 ? data.substr(32, 16) : data.substr(0, 16); + output += "\n"; + } + else + { + output += m_typeToName[t]; + output += " = "; + output += data; + output += "\n"; + } + } + + void OutputData(std::string &output, DataType t, int i) + { + OutputData(output, t, IntToString(i)); + } + + void OutputData(std::string &output, DataType t, const SecByteBlock &data) + { + std::string hexData; + StringSource(data, true, new HexEncoder(new StringSink(hexData), false)); + OutputData(output, t, hexData); + } + + void OutputGivenData(std::string &output, DataType t, bool optional = false) + { + if (m_data.find(m_typeToName[t]) == m_data.end()) + { + if (optional) + return; + throw Exception(Exception::OTHER_ERROR, "TestDataParser: key not found: " + m_typeToName[t]); + } + + OutputData(output, t, m_data[m_typeToName[t]]); + } + + template <class T> + BlockCipher * NewBT(T *) + { + if (!m_encrypt && (m_mode == "ECB" || m_mode == "CBC")) + return new typename T::Decryption; + else + return new typename T::Encryption; + } + + template <class T> + SymmetricCipher * NewMode(T *, BlockCipher &bt, const byte *iv) + { + if (!m_encrypt) + return new typename T::Decryption(bt, iv, m_feedbackSize/8); + else + return new typename T::Encryption(bt, iv, m_feedbackSize/8); + } + + static inline void Xor(SecByteBlock &z, const SecByteBlock &x, const SecByteBlock &y) + { + assert(x.size() == y.size()); + z.resize(x.size()); + xorbuf(z, x, y, x.size()); + } + + SecByteBlock UpdateKey(SecByteBlock key, const SecByteBlock *text) + { + unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000; + int keySize = key.size(), blockSize = text[0].size(); + SecByteBlock x(keySize); + for (int k=0; k<keySize;) + { + int pos = innerCount * blockSize - keySize + k; + memcpy(x + k, text[pos / blockSize] + pos % blockSize, blockSize - pos % blockSize); + k += blockSize - pos % blockSize; + } + + if (m_algorithm == "TDES" || m_algorithm == "DES") + { + for (int i=0; i<keySize; i+=8) + { + xorbuf(key+i, x+keySize-8-i, 8); + DES::CorrectKeyParityBits(key+i); + } + } + else + xorbuf(key, x, keySize); + + return key; + } + + static inline void AssignLeftMostBits(SecByteBlock &z, const SecByteBlock &x, unsigned int K) + { + z.Assign(x, K/8); + } + + virtual void DoTest() + { + std::string output; + + if (m_algorithm == "DSS") + { + if (m_test == "sha") + { + assert(m_compactString.size() >= 2); + assert(m_compactString[0] == m_compactString.size()-2); + bool b = !!m_compactString[1]; + Integer m; + unsigned int bitLength = 0; + + for (unsigned int j = 2; j < m_compactString.size(); j++) + { + m <<= m_compactString[j]; + for (unsigned int k = 0; k < m_compactString[j]; k++) + m.SetBit(k, b); + bitLength += m_compactString[j]; + b = !b; + } + m_compactString.clear(); + assert(bitLength % 8 == 0); + + SecByteBlock message(bitLength / 8); + m.Encode(message, message.size()); + SHA sha; + + if (m_bracketString == "SHS Type 3 Strings") + { + SecByteBlock m1; + for (int j = 0; j < 100; j++) + { + for (word32 i = 1; i <= 50000; i++) + { + m1.resize(message.size() + j/4 + 3 + 4); + memcpy(m1, message, message.size()); + memset(m1 + message.size(), 0, j/4 + 3); + PutWord(false, BIG_ENDIAN_ORDER, m1 + m1.size() - 4, i); + message.resize(sha.DigestSize()); + sha.CalculateDigest(message, m1, m1.size()); + } + StringSource(message, message.size(), true, new HexEncoder(new StringSink(output))); + output += " ^\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + } + else + { + StringSource(message, message.size(), true, new HashFilter(sha, new HexEncoder(new StringSink(output)))); + output += " ^\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + } + } + else if (m_test == "prime") + { + Integer p((m_data["Prime"] + "h").c_str()); + OutputData(output, "result", VerifyPrime(m_rng, p, 2) ? "P" : "F"); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + else if (m_test == "pqg") + { + int n = atol(m_data["N"].c_str()); + for (int i=0; i<n; i++) + { + Integer p, q, h, g; + int counter; + + SecByteBlock seed(SHA::DIGESTSIZE); + do + { + m_rng.GenerateBlock(seed, seed.size()); + } + while (!DSA::GeneratePrimes(seed, seed.size()*8, counter, p, 1024, q)); + h.Randomize(m_rng, 2, p-2); + g = a_exp_b_mod_c(h, (p-1)/q, p); + + OutputData(output, "P", p); + OutputData(output, "Q", q); + OutputData(output, "G", g); + OutputData(output, "Seed", seed); + OutputData(output, "H", h); + OutputData(output, "c", counter); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + } + else if (m_test == "xy") + { + Integer p((m_data["P"] + "h").c_str()); + Integer q((m_data["Q"] + "h").c_str()); + Integer g((m_data["G"] + "h").c_str()); + + for (int i=0; i<10; i++) + { + DSA::Signer priv(m_rng, p, q, g); + DSA::Verifier pub(priv); + + OutputData(output, "X", priv.GetKey().GetPrivateExponent()); + OutputData(output, "Y", pub.GetKey().GetPublicElement()); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + } + else if (m_test == "gensig") + { + Integer p((m_data["P"] + "h").c_str()); + Integer q((m_data["Q"] + "h").c_str()); + Integer g((m_data["G"] + "h").c_str()); + Integer x((m_data["X"] + "h").c_str()); + DSA::Signer signer(p, q, g, x); + + SecByteBlock sig(signer.SignatureLength()); + StringSource(m_data["Msg"], true, new HexDecoder(new SignerFilter(m_rng, signer, new ArraySink(sig, sig.size())))); + OutputData(output, "Sig", sig); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + else if (m_test == "versig") + { + Integer p((m_data["P"] + "h").c_str()); + Integer q((m_data["Q"] + "h").c_str()); + Integer g((m_data["G"] + "h").c_str()); + Integer y((m_data["Y"] + "h").c_str()); + DSA::Verifier verifier(p, q, g, y); + + HexDecoder filter(new SignatureVerificationFilter(verifier)); + StringSource(m_data["Sig"], true, new Redirector(filter, false)); + StringSource(m_data["Msg"], true, new Redirector(filter, false)); + filter.MessageEnd(); + byte b; + filter.Get(b); + OutputData(output, "result", b ? "P" : "F"); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + else if (m_test == "verpqg") + { + Integer p((m_data["P"] + "h").c_str()); + Integer q((m_data["Q"] + "h").c_str()); + Integer g((m_data["G"] + "h").c_str()); + Integer h((m_data["H"] + "h").c_str()); + int c = atol(m_data["c"].c_str()); + SecByteBlock seed(m_data["Seed"].size()/2); + StringSource(m_data["Seed"], true, new HexDecoder(new ArraySink(seed, seed.size()))); + + Integer p1, q1; + bool result = DSA::GeneratePrimes(seed, seed.size()*8, c, p1, 1024, q1, true); + result = result && (p1 == p && q1 == q); + result = result && g == a_exp_b_mod_c(h, (p-1)/q, p); + + OutputData(output, "result", result ? "P" : "F"); + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + + return; + } + + SecByteBlock &key = m_data2[KEY_T]; + + if (m_algorithm == "TDES") + { + if (!m_data["KEY1"].empty()) + { + const std::string keys[3] = {m_data["KEY1"], m_data["KEY2"], m_data["KEY3"]}; + key.resize(24); + HexDecoder hexDec(new ArraySink(key, key.size())); + for (int i=0; i<3; i++) + hexDec.Put((byte *)keys[i].data(), keys[i].size()); + + if (keys[0] == keys[2]) + { + if (keys[0] == keys[1]) + key.resize(8); + else + key.resize(16); + } + else + key.resize(24); + } + } + + member_ptr<BlockCipher> pBT; + if (m_algorithm == "DES") + pBT.reset(NewBT((DES*)0)); + else if (m_algorithm == "TDES") + { + if (key.size() == 8) + pBT.reset(NewBT((DES*)0)); + else if (key.size() == 16) + pBT.reset(NewBT((DES_EDE2*)0)); + else + pBT.reset(NewBT((DES_EDE3*)0)); + } + else if (m_algorithm == "SKIPJACK") + pBT.reset(NewBT((SKIPJACK*)0)); + else if (m_algorithm == "AES") + pBT.reset(NewBT((AES*)0)); + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected algorithm: " + m_algorithm); + + if (!pBT->IsValidKeyLength(key.size())) + key.CleanNew(pBT->DefaultKeyLength()); // for Scbcvrct + pBT->SetKey(key.data(), key.size()); + + SecByteBlock &iv = m_data2[IV]; + if (iv.empty()) + iv.CleanNew(pBT->BlockSize()); + + member_ptr<SymmetricCipher> pCipher; + unsigned int K = m_feedbackSize; + + if (m_mode == "ECB") + pCipher.reset(NewMode((ECB_Mode_ExternalCipher*)0, *pBT, iv)); + else if (m_mode == "CBC") + pCipher.reset(NewMode((CBC_Mode_ExternalCipher*)0, *pBT, iv)); + else if (m_mode == "CFB") + pCipher.reset(NewMode((CFB_Mode_ExternalCipher*)0, *pBT, iv)); + else if (m_mode == "OFB") + pCipher.reset(NewMode((OFB_Mode_ExternalCipher*)0, *pBT, iv)); + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); + + bool encrypt = m_encrypt; + + if (m_test == "MONTE") + { + SecByteBlock KEY[401]; + KEY[0] = key; + int keySize = key.size(); + int blockSize = pBT->BlockSize(); + + SecByteBlock IB[10001], OB[10001], PT[10001], CT[10001], RESULT[10001], TXT[10001], CV[10001]; + PT[0] = GetData("PLAINTEXT"); + CT[0] = GetData("CIPHERTEXT"); + CV[0] = IB[0] = iv; + TXT[0] = GetData("TEXT"); + + unsigned int outerCount = (m_algorithm == "AES") ? 100 : 400; + unsigned int innerCount = (m_algorithm == "AES") ? 1000 : 10000; + + for (int i=0; i<outerCount; i++) + { + pBT->SetKey(KEY[i], keySize); + + for (int j=0; j<innerCount; j++) + { + if (m_mode == "ECB") + { + if (encrypt) + { + IB[j] = PT[j]; + CT[j].resize(blockSize); + pBT->ProcessBlock(IB[j], CT[j]); + PT[j+1] = CT[j]; + } + else + { + IB[j] = CT[j]; + PT[j].resize(blockSize); + pBT->ProcessBlock(IB[j], PT[j]); + CT[j+1] = PT[j]; + } + } + else if (m_mode == "OFB") + { + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + Xor(RESULT[j], OB[j], TXT[j]); + TXT[j+1] = IB[j]; + IB[j+1] = OB[j]; + } + else if (m_mode == "CBC") + { + if (encrypt) + { + Xor(IB[j], PT[j], CV[j]); + CT[j].resize(blockSize); + pBT->ProcessBlock(IB[j], CT[j]); + PT[j+1] = CV[j]; + CV[j+1] = CT[j]; + } + else + { + IB[j] = CT[j]; + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + Xor(PT[j], OB[j], CV[j]); + CV[j+1] = CT[j]; + CT[j+1] = PT[j]; + } + } + else if (m_mode == "CFB") + { + if (encrypt) + { + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + AssignLeftMostBits(CT[j], OB[j], K); + Xor(CT[j], CT[j], PT[j]); + AssignLeftMostBits(PT[j+1], IB[j], K); + IB[j+1].resize(blockSize); + memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8); + memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8); + } + else + { + OB[j].resize(blockSize); + pBT->ProcessBlock(IB[j], OB[j]); + AssignLeftMostBits(PT[j], OB[j], K); + Xor(PT[j], PT[j], CT[j]); + IB[j+1].resize(blockSize); + memcpy(IB[j+1], IB[j]+K/8, blockSize-K/8); + memcpy(IB[j+1]+blockSize-K/8, CT[j], K/8); + AssignLeftMostBits(CT[j+1], OB[j], K); + } + } + else + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected mode: " + m_mode); + } + + OutputData(output, COUNT, i); + OutputData(output, KEY_T, KEY[i]); + if (m_mode == "CBC") + OutputData(output, IV, CV[0]); + if (m_mode == "OFB" || m_mode == "CFB") + OutputData(output, IV, IB[0]); + if (m_mode == "ECB" || m_mode == "CBC" || m_mode == "CFB") + { + if (encrypt) + { + OutputData(output, INPUT, PT[0]); + OutputData(output, OUTPUT, CT[innerCount-1]); + KEY[i+1] = UpdateKey(KEY[i], CT); + } + else + { + OutputData(output, INPUT, CT[0]); + OutputData(output, OUTPUT, PT[innerCount-1]); + KEY[i+1] = UpdateKey(KEY[i], PT); + } + PT[0] = PT[innerCount]; + IB[0] = IB[innerCount]; + CV[0] = CV[innerCount]; + CT[0] = CT[innerCount]; + } + else if (m_mode == "OFB") + { + OutputData(output, INPUT, TXT[0]); + OutputData(output, OUTPUT, RESULT[innerCount-1]); + KEY[i+1] = UpdateKey(KEY[i], RESULT); + Xor(TXT[0], TXT[0], IB[innerCount-1]); + IB[0] = OB[innerCount-1]; + } + output += "\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + } + } + else if (m_test == "MCT") + { + SecByteBlock KEY[101]; + KEY[0] = key; + int keySize = key.size(); + int blockSize = pBT->BlockSize(); + + SecByteBlock ivs[101], inputs[1001], outputs[1001]; + ivs[0] = iv; + inputs[0] = m_data2[INPUT]; + + for (int i=0; i<100; i++) + { + pCipher->SetKey(KEY[i], keySize, MakeParameters(Name::IV(), (const byte *)ivs[i])(Name::FeedbackSize(), (int)K/8)); + + for (int j=0; j<1000; j++) + { + outputs[j] = inputs[j]; + pCipher->ProcessString(outputs[j], outputs[j].size()); + if (K==8 && m_mode == "CFB") + { + if (j<16) + inputs[j+1].Assign(ivs[i]+j, 1); + else + inputs[j+1] = outputs[j-16]; + } + else if (m_mode == "ECB") + inputs[j+1] = outputs[j]; + else if (j == 0) + inputs[j+1] = ivs[i]; + else + inputs[j+1] = outputs[j-1]; + } + + OutputData(output, KEY_T, KEY[i]); + if (m_mode != "ECB") + OutputData(output, IV, ivs[i]); + OutputData(output, INPUT, inputs[0]); + OutputData(output, OUTPUT, outputs[999]); + output += "\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + output.resize(0); + + KEY[i+1] = UpdateKey(KEY[i], outputs); + ivs[i+1].CleanNew(pCipher->IVSize()); + ivs[i+1] = UpdateKey(ivs[i+1], outputs); + if (K==8 && m_mode == "CFB") + inputs[0] = outputs[999-16]; + else if (m_mode == "ECB") + inputs[0] = outputs[999]; + else + inputs[0] = outputs[998]; + } + } + else + { + assert(m_test == "KAT"); + + SecByteBlock &input = m_data2[INPUT]; + SecByteBlock result(input.size()); + member_ptr<Filter> pFilter(new StreamTransformationFilter(*pCipher, new ArraySink(result, result.size()), StreamTransformationFilter::NO_PADDING)); + StringSource(input.data(), input.size(), true, pFilter.release()); + + OutputGivenData(output, COUNT, true); + OutputData(output, KEY_T, key); + OutputGivenData(output, IV, true); + OutputGivenData(output, INPUT); + OutputData(output, OUTPUT, result); + output += "\n"; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + } + } + + std::vector<std::string> Tokenize(const std::string &line) + { + std::vector<std::string> result; + std::string s; + for (int i=0; i<line.size(); i++) + { + if (isalnum(line[i]) || line[i] == '^') + s += line[i]; + else if (!s.empty()) + { + result.push_back(s); + s = ""; + } + if (line[i] == '=') + result.push_back("="); + } + result.push_back(s); + return result; + } + + bool IsolatedMessageEnd(bool blocking) + { + if (!blocking) + throw BlockingInputOnly("TestDataParser"); + + m_line.resize(0); + m_inQueue.TransferTo(StringSink(m_line).Ref()); + + if (m_line[0] == '#') + return false; + + bool copyLine = false; + + if (m_line[0] == '[') + { + m_bracketString = m_line.substr(1, m_line.size()-2); + if (m_bracketString == "ENCRYPT") + SetEncrypt(true); + if (m_bracketString == "DECRYPT") + SetEncrypt(false); + copyLine = true; + } + + if (m_line.substr(0, 2) == "H>") + { + assert(m_test == "sha"); + m_bracketString = m_line.substr(2, m_line.size()-4); + m_line = m_line.substr(0, 13) + "Hashes<H"; + copyLine = true; + } + + if (m_line == "D>") + copyLine = true; + + if (m_line == "<D") + { + m_line += "\n"; + copyLine = true; + } + + if (copyLine) + { + m_line += '\n'; + AttachedTransformation()->Put((byte *)m_line.data(), m_line.size(), blocking); + return false; + } + + std::vector<std::string> tokens = Tokenize(m_line); + + if (m_algorithm == "DSS" && m_test == "sha") + { + for (int i = 0; i < tokens.size(); i++) + { + if (tokens[i] == "^") + DoTest(); + else if (tokens[i] != "") + m_compactString.push_back(atol(tokens[i].c_str())); + } + } + else + { + if (!m_line.empty() && m_algorithm == "DSS" && m_test != "pqg") + { + std::string output = m_line + '\n'; + AttachedTransformation()->Put((byte *)output.data(), output.size()); + } + + for (int i = 0; i < tokens.size(); i++) + { + if (m_firstLine && m_algorithm != "DSS") + { + if (tokens[i] == "Encrypt" || tokens[i] == "OFB") + SetEncrypt(true); + else if (tokens[i] == "Decrypt") + SetEncrypt(false); + else if (tokens[i] == "Modes") + m_test = "MONTE"; + } + else + { + if (tokens[i] != "=") + continue; + + if (i == 0) + throw Exception(Exception::OTHER_ERROR, "TestDataParser: unexpected data: " + m_line); + + const std::string &key = tokens[i-1]; + std::string &data = m_data[key]; + data = tokens[i+1]; + DataType t = m_nameToType[key]; + m_typeToName[t] = key; + SecByteBlock data2(data.size() / 2); + StringSource(data, true, new HexDecoder(new ArraySink(data2, data2.size()))); + m_data2[t] = data2; + + if (key == m_trigger || (t == OUTPUT && !m_data2[INPUT].empty())) + DoTest(); + } + } + } + + m_firstLine = false; + + return false; + } + + inline const SecByteBlock & GetData(const std::string &key) + { + return m_data2[m_nameToType[key]]; + } + + std::string m_algorithm, m_test, m_mode, m_line, m_bracketString, m_trigger; + unsigned int m_feedbackSize, m_blankLineTransition; + bool m_encrypt, m_firstLine; + + typedef std::map<std::string, DataType> NameToTypeMap; + NameToTypeMap m_nameToType; + typedef std::map<DataType, std::string> TypeToNameMap; + TypeToNameMap m_typeToName; + + typedef std::map<std::string, std::string> Map; + Map m_data; // raw data + typedef std::map<DataType, SecByteBlock> Map2; + Map2 m_data2; + + AutoSeededX917RNG<DES_EDE3> m_rng; + std::vector<unsigned int> m_compactString; +}; +*/ + +/* +int main (int argc, char **argv) +{ + std::string algorithm = argv[1]; + std::string pathname = argv[2]; + i = pathname.find_last_of("\\/"); + std::string filename = pathname.substr(i == std::string::npos ? 0 : i+1); + std::string mode; + if (filename[0] == 'S' || filename[0] == 'T') + mode = filename.substr(1, 3); + else + mode = filename.substr(0, 3); + for (i = 0; i<mode.size(); i++) + mode[i] = toupper(mode[i]); + unsigned int feedbackSize = mode == "CFB" ? atoi(filename.substr(filename.find_first_of("0123456789")).c_str()) : 0; + std::string test; + if (algorithm == "DSS") + test = filename.substr(0, filename.size() - 4); + else if (filename.find("Monte") != std::string::npos) + test = "MONTE"; + else if (filename.find("MCT") != std::string::npos) + test = "MCT"; + else + test = "KAT"; + bool encrypt = (filename.find("vrct") == std::string::npos); + + BufferedTransformation *pSink = NULL; + + if (argc > 3) + { + std::string outDir = argv[3]; + if (*outDir.rbegin() != '\\' && *outDir.rbegin() != '/') + outDir += '/'; + std::string outPathname = outDir + filename.substr(0, filename.size() - 3) + "rsp"; + pSink = new FileSink(outPathname.c_str(), false); + } + else + pSink = new FileSink(cout); + + FileSource(pathname.c_str(), true, new LineBreakParser(new TestDataParser(algorithm, test, mode, feedbackSize, encrypt, pSink)), false); +} +*/ diff --git a/fipstest.cpp b/fipstest.cpp index 10368ae..9f740f0 100644 --- a/fipstest.cpp +++ b/fipstest.cpp @@ -42,6 +42,7 @@ void X917RNG_KnownAnswerTest( unsigned int deterministicTimeVector, CIPHER *dummy = NULL) { +#ifdef OS_RNG_AVAILABLE std::string decodedKey, decodedSeed; StringSource(key, true, new HexDecoder(new StringSink(decodedKey))); StringSource(seed, true, new HexDecoder(new StringSink(decodedSeed))); @@ -49,6 +50,9 @@ void X917RNG_KnownAnswerTest( AutoSeededX917RNG<CIPHER> rng; rng.Reseed((const byte *)decodedKey.data(), decodedKey.size(), (const byte *)decodedSeed.data(), deterministicTimeVector); KnownAnswerTest(rng, output); +#else + throw 0; +#endif } void KnownAnswerTest(StreamTransformation &encryption, StreamTransformation &decryption, const char *plaintext, const char *ciphertext) @@ -128,19 +132,25 @@ void MAC_KnownAnswerTest(const char *key, const char *message, const char *diges template <class SCHEME> void SignatureKnownAnswerTest(const char *key, const char *message, const char *signature, SCHEME *dummy = NULL) { +#ifdef OS_RNG_AVAILABLE + AutoSeededX917RNG<DES_EDE3> rng; +#else + RandomNumberGenerator &rng = NullRNG(); +#endif + typename SCHEME::Signer signer(StringSource(key, true, new HexDecoder).Ref()); typename SCHEME::Verifier verifier(signer); EqualityComparisonFilter comparison; - StringSource(message, true, new SignerFilter(NullRNG(), signer, new ChannelSwitch(comparison, "0"))); + StringSource(message, true, new SignerFilter(rng, signer, new ChannelSwitch(comparison, "0"))); StringSource(signature, true, new HexDecoder(new ChannelSwitch(comparison, "1"))); comparison.ChannelMessageSeriesEnd("0"); comparison.ChannelMessageSeriesEnd("1"); VerifierFilter verifierFilter(verifier, NULL, VerifierFilter::SIGNATURE_AT_BEGIN | VerifierFilter::THROW_EXCEPTION); - StringSource(signature, true, new HexDecoder(new Redirector(verifierFilter, false))); + StringSource(signature, true, new HexDecoder(new Redirector(verifierFilter, Redirector::DATA_ONLY))); StringSource(message, true, new Redirector(verifierFilter)); } @@ -222,7 +232,33 @@ void DoPowerUpSelfTest(const char *moduleFilename, const byte *expectedModuleSha SHA1 sha; HashVerifier verifier(sha); verifier.Put(expectedModuleSha1Digest, sha.DigestSize()); - FileStore(moduleFilename).TransferAllTo(verifier); + FileStore file(moduleFilename); + +#ifdef CRYPTOPP_WIN32_AVAILABLE + // try to hash from memory first + HMODULE h = GetModuleHandle(moduleFilename); + IMAGE_DOS_HEADER *ph = (IMAGE_DOS_HEADER *)h; + IMAGE_NT_HEADERS *phnt = (IMAGE_NT_HEADERS *)((byte *)h + ph->e_lfanew); + IMAGE_SECTION_HEADER *phs = (IMAGE_SECTION_HEADER *)((byte *)&phnt->OptionalHeader + phnt->FileHeader.SizeOfOptionalHeader); + DWORD SectionSize = STDMIN(phs->SizeOfRawData, phs->Misc.VirtualSize); + + file.TransferTo(verifier, phs->PointerToRawData); + verifier.Put((const byte *)h + phs->VirtualAddress, SectionSize); + file.Skip(SectionSize); +#endif + file.TransferAllTo(verifier); + +#ifdef CRYPTOPP_WIN32_AVAILABLE + // if that fails (could be caused by debug breakpoints or DLL base relocation modifying image in memory), + // hash from disk instead + if (!verifier.GetLastResult()) + { + verifier.Put(expectedModuleSha1Digest, sha.DigestSize()); + file.Initialize(MakeParameters(Name::InputFileName(), moduleFilename)); + file.TransferAllTo(verifier); + } +#endif + if (!verifier.GetLastResult()) { #ifdef CRYPTOPP_WIN32_AVAILABLE @@ -80,8 +80,17 @@ void MD2::Update(const byte *buf, unsigned int len) t=0; for(i=0; i<18; i++) { - for(j=0; j<48; j++) - t=m_X[j]^=S[t]; + for(j=0; j<48; j+=8) + { + t=m_X[j+0]^=S[t]; + t=m_X[j+1]^=S[t]; + t=m_X[j+2]^=S[t]; + t=m_X[j+3]^=S[t]; + t=m_X[j+4]^=S[t]; + t=m_X[j+5]^=S[t]; + t=m_X[j+6]^=S[t]; + t=m_X[j+7]^=S[t]; + } t=(t+i) & 0xFF; } } @@ -480,6 +480,31 @@ inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, wo : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24); } +#ifdef WORD64_AVAILABLE +inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, word64*) +{ + return (order == BIG_ENDIAN_ORDER) + ? + (word64(block[7]) | + (word64(block[6]) << 8) | + (word64(block[5]) << 16) | + (word64(block[4]) << 24) | + (word64(block[3]) << 32) | + (word64(block[2]) << 40) | + (word64(block[1]) << 48) | + (word64(block[0]) << 56)) + : + (word64(block[0]) | + (word64(block[1]) << 8) | + (word64(block[2]) << 16) | + (word64(block[3]) << 24) | + (word64(block[4]) << 32) | + (word64(block[5]) << 40) | + (word64(block[6]) << 48) | + (word64(block[7]) << 56)); +} +#endif + template <class T> inline T UnalignedGetWord(ByteOrder order, const byte *block, T*dummy=NULL) { @@ -537,6 +562,46 @@ inline void UnalignedPutWord(ByteOrder order, byte *block, word32 value, const b } } +#ifdef WORD64_AVAILABLE +inline void UnalignedPutWord(ByteOrder order, byte *block, word64 value, const byte *xorBlock = NULL) +{ + if (order == BIG_ENDIAN_ORDER) + { + block[0] = GETBYTE(value, 7); + block[1] = GETBYTE(value, 6); + block[2] = GETBYTE(value, 5); + block[3] = GETBYTE(value, 4); + block[4] = GETBYTE(value, 3); + block[5] = GETBYTE(value, 2); + block[6] = GETBYTE(value, 1); + block[7] = GETBYTE(value, 0); + } + else + { + block[0] = GETBYTE(value, 0); + block[1] = GETBYTE(value, 1); + block[2] = GETBYTE(value, 2); + block[3] = GETBYTE(value, 3); + block[4] = GETBYTE(value, 4); + block[5] = GETBYTE(value, 5); + block[6] = GETBYTE(value, 6); + block[7] = GETBYTE(value, 7); + } + + if (xorBlock) + { + block[0] ^= xorBlock[0]; + block[1] ^= xorBlock[1]; + block[2] ^= xorBlock[2]; + block[3] ^= xorBlock[3]; + block[4] ^= xorBlock[4]; + block[5] ^= xorBlock[5]; + block[6] ^= xorBlock[6]; + block[7] ^= xorBlock[7]; + } +} +#endif + template <class T> inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block) { diff --git a/regtest.cpp b/regtest.cpp index d691d46..60e59f7 100644 --- a/regtest.cpp +++ b/regtest.cpp @@ -1,5 +1,6 @@ #include "factory.h" +#include "modes.h" #include "dh.h" #include "esign.h" #include "md2.h" @@ -10,6 +11,10 @@ #include "ripemd.h" #include "dsa.h" #include "seal.h" +#include "whrlpool.h" +#include "ttmac.h" +#include "camellia.h" +#include "shacal2.h" USING_NAMESPACE(CryptoPP) @@ -20,9 +25,11 @@ void RegisterFactories() RegisterDefaultFactoryFor<HashTransformation, SHA256>("SHA-256"); RegisterDefaultFactoryFor<HashTransformation, SHA384>("SHA-384"); RegisterDefaultFactoryFor<HashTransformation, SHA512>("SHA-512"); + RegisterDefaultFactoryFor<HashTransformation, Whirlpool>("Whirlpool"); RegisterDefaultFactoryFor<MessageAuthenticationCode, HMAC<MD5> >("HMAC(MD5)"); RegisterDefaultFactoryFor<MessageAuthenticationCode, HMAC<SHA1> >("HMAC(SHA-1)"); RegisterDefaultFactoryFor<MessageAuthenticationCode, HMAC<RIPEMD160> >("HMAC(RIPEMD-160)"); + RegisterDefaultFactoryFor<MessageAuthenticationCode, TTMAC >("Two-Track-MAC"); RegisterAsymmetricCipherDefaultFactories<RSAES<OAEP<SHA1> > >("RSA/OAEP-MGF1(SHA-1)"); RegisterAsymmetricCipherDefaultFactories<DLIES<> >("DLIES(NoCofactorMultiplication, KDF2(SHA-1), XOR, HMAC(SHA-1), DHAES)"); RegisterSignatureSchemeDefaultFactories<DSA>("DSA(1363)"); @@ -34,4 +41,6 @@ void RegisterFactories() RegisterSignatureSchemeDefaultFactories<RWSS<P1363_EMSA2, SHA1> >("RW/EMSA2(SHA-1)"); RegisterSignatureSchemeDefaultFactories<RSASS<PSS, SHA1> >("RSA/PSS-MGF1(SHA-1)"); RegisterSymmetricCipherDefaultFactories<SEAL<> >("SEAL-3.0-BE"); + RegisterSymmetricCipherDefaultFactories<ECB_Mode<Camellia> >("Camellia(ECB)"); + RegisterSymmetricCipherDefaultFactories<ECB_Mode<SHACAL2> >("SHACAL-2(ECB)"); } @@ -1,4 +1,7 @@ -// ripemd.cpp - written and placed in the public domain by Wei Dai +// ripemd.cpp +// RIPEMD-160 written and placed in the public domain by Wei Dai +// RIPEMD-320, RIPEMD-128, RIPEMD-256 written by Kevin Springle +// and also placed in the public domain #include "pch.h" #include "ripemd.h" @@ -6,22 +9,6 @@ NAMESPACE_BEGIN(CryptoPP) -void RIPEMD160::Init() -{ - m_digest[0] = 0x67452301L; - m_digest[1] = 0xefcdab89L; - m_digest[2] = 0x98badcfeL; - m_digest[3] = 0x10325476L; - m_digest[4] = 0xc3d2e1f0L; -} - -void RIPEMD160::Transform (word32 *digest, const word32 *X) -{ -#define Subround(f, a, b, c, d, e, x, s, k) \ - a += f(b, c, d) + x + k;\ - a = rotlFixed((word32)a, s) + e;\ - c = rotlFixed((word32)c, 10U) - #define F(x, y, z) (x ^ y ^ z) #define G(x, y, z) (z ^ (x & (y^z))) #define H(x, y, z) (z ^ (x | ~y)) @@ -39,6 +26,25 @@ void RIPEMD160::Transform (word32 *digest, const word32 *X) #define k8 0x7a6d76e9UL #define k9 0 +// ************************************************************* + +// for 160 and 320 +#define Subround(f, a, b, c, d, e, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlFixed((word32)a, s) + e;\ + c = rotlFixed((word32)c, 10U) + +void RIPEMD160::Init() +{ + m_digest[0] = 0x67452301L; + m_digest[1] = 0xefcdab89L; + m_digest[2] = 0x98badcfeL; + m_digest[3] = 0x10325476L; + m_digest[4] = 0xc3d2e1f0L; +} + +void RIPEMD160::Transform (word32 *digest, const word32 *X) +{ unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; a1 = a2 = digest[0]; b1 = b2 = digest[1]; @@ -224,4 +230,574 @@ void RIPEMD160::Transform (word32 *digest, const word32 *X) digest[0] = c1; } +// ************************************************************* + +void RIPEMD320::Init() +{ + m_digest[0] = 0x67452301L; + m_digest[1] = 0xefcdab89L; + m_digest[2] = 0x98badcfeL; + m_digest[3] = 0x10325476L; + m_digest[4] = 0xc3d2e1f0L; + m_digest[5] = 0x76543210L; + m_digest[6] = 0xfedcba98L; + m_digest[7] = 0x89abcdefL; + m_digest[8] = 0x01234567L; + m_digest[9] = 0x3c2d1e0fL; +} + +void RIPEMD320::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, e1, a2, b2, c2, d2, e2, t; + a1 = digest[0]; + b1 = digest[1]; + c1 = digest[2]; + d1 = digest[3]; + e1 = digest[4]; + a2 = digest[5]; + b2 = digest[6]; + c2 = digest[7]; + d2 = digest[8]; + e2 = digest[9]; + + Subround(F, a1, b1, c1, d1, e1, X[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, X[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, X[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, X[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, X[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, X[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, X[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, X[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, X[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, X[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, X[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, X[15], 8, k0); + + Subround(J, a2, b2, c2, d2, e2, X[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, X[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, X[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, X[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, X[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, X[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, X[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, X[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, X[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, X[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, X[12], 6, k5); + + t = a1; a1 = a2; a2 = t; + + Subround(G, e1, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, X[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, X[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, X[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, X[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, X[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, X[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, X[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, X[ 8], 12, k1); + + Subround(I, e2, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, X[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, X[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, X[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, X[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, X[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, X[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, X[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, X[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, X[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, X[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, X[ 2], 11, k6); + + t = b1; b1 = b2; b2 = t; + + Subround(H, d1, e1, a1, b1, c1, X[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, X[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, X[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, X[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, X[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, X[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, X[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, X[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, X[12], 5, k2); + + Subround(H, d2, e2, a2, b2, c2, X[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, X[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, X[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, X[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, X[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, X[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, X[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, X[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, X[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, X[13], 5, k7); + + t = c1; c1 = c2; c2 = t; + + Subround(I, c1, d1, e1, a1, b1, X[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, X[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, X[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, X[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, X[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, X[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, X[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, X[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, X[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, X[ 2], 12, k3); + + Subround(G, c2, d2, e2, a2, b2, X[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, X[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, X[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, X[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, X[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, X[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, X[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, X[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, X[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, X[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, X[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, X[14], 8, k8); + + t = d1; d1 = d2; d2 = t; + + Subround(J, b1, c1, d1, e1, a1, X[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, X[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, X[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, X[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, X[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, X[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, X[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, X[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, X[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, X[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, X[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, X[13], 6, k4); + + Subround(F, b2, c2, d2, e2, a2, X[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, X[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, X[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, X[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, X[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, X[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, X[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, X[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, X[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, X[11], 11, k9); + + t = e1; e1 = e2; e2 = t; + + digest[0] += a1; + digest[1] += b1; + digest[2] += c1; + digest[3] += d1; + digest[4] += e1; + digest[5] += a2; + digest[6] += b2; + digest[7] += c2; + digest[8] += d2; + digest[9] += e2; +} + +#undef Subround + +// ************************************************************* + +// for 128 and 256 +#define Subround(f, a, b, c, d, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlFixed((word32)a, s); + +void RIPEMD128::Init() +{ + m_digest[0] = 0x67452301L; + m_digest[1] = 0xefcdab89L; + m_digest[2] = 0x98badcfeL; + m_digest[3] = 0x10325476L; +} + +void RIPEMD128::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, a2, b2, c2, d2; + a1 = a2 = digest[0]; + b1 = b2 = digest[1]; + c1 = c2 = digest[2]; + d1 = d2 = digest[3]; + + Subround(F, a1, b1, c1, d1, X[ 0], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 1], 14, k0); + Subround(F, c1, d1, a1, b1, X[ 2], 15, k0); + Subround(F, b1, c1, d1, a1, X[ 3], 12, k0); + Subround(F, a1, b1, c1, d1, X[ 4], 5, k0); + Subround(F, d1, a1, b1, c1, X[ 5], 8, k0); + Subround(F, c1, d1, a1, b1, X[ 6], 7, k0); + Subround(F, b1, c1, d1, a1, X[ 7], 9, k0); + Subround(F, a1, b1, c1, d1, X[ 8], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 9], 13, k0); + Subround(F, c1, d1, a1, b1, X[10], 14, k0); + Subround(F, b1, c1, d1, a1, X[11], 15, k0); + Subround(F, a1, b1, c1, d1, X[12], 6, k0); + Subround(F, d1, a1, b1, c1, X[13], 7, k0); + Subround(F, c1, d1, a1, b1, X[14], 9, k0); + Subround(F, b1, c1, d1, a1, X[15], 8, k0); + + Subround(G, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, X[10], 11, k1); + Subround(G, d1, a1, b1, c1, X[ 6], 9, k1); + Subround(G, c1, d1, a1, b1, X[15], 7, k1); + Subround(G, b1, c1, d1, a1, X[ 3], 15, k1); + Subround(G, a1, b1, c1, d1, X[12], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 0], 12, k1); + Subround(G, c1, d1, a1, b1, X[ 9], 15, k1); + Subround(G, b1, c1, d1, a1, X[ 5], 9, k1); + Subround(G, a1, b1, c1, d1, X[ 2], 11, k1); + Subround(G, d1, a1, b1, c1, X[14], 7, k1); + Subround(G, c1, d1, a1, b1, X[11], 13, k1); + Subround(G, b1, c1, d1, a1, X[ 8], 12, k1); + + Subround(H, a1, b1, c1, d1, X[ 3], 11, k2); + Subround(H, d1, a1, b1, c1, X[10], 13, k2); + Subround(H, c1, d1, a1, b1, X[14], 6, k2); + Subround(H, b1, c1, d1, a1, X[ 4], 7, k2); + Subround(H, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, X[ 2], 14, k2); + Subround(H, d1, a1, b1, c1, X[ 7], 8, k2); + Subround(H, c1, d1, a1, b1, X[ 0], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 6], 6, k2); + Subround(H, a1, b1, c1, d1, X[13], 5, k2); + Subround(H, d1, a1, b1, c1, X[11], 12, k2); + Subround(H, c1, d1, a1, b1, X[ 5], 7, k2); + Subround(H, b1, c1, d1, a1, X[12], 5, k2); + + Subround(I, a1, b1, c1, d1, X[ 1], 11, k3); + Subround(I, d1, a1, b1, c1, X[ 9], 12, k3); + Subround(I, c1, d1, a1, b1, X[11], 14, k3); + Subround(I, b1, c1, d1, a1, X[10], 15, k3); + Subround(I, a1, b1, c1, d1, X[ 0], 14, k3); + Subround(I, d1, a1, b1, c1, X[ 8], 15, k3); + Subround(I, c1, d1, a1, b1, X[12], 9, k3); + Subround(I, b1, c1, d1, a1, X[ 4], 8, k3); + Subround(I, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, X[14], 8, k3); + Subround(I, d1, a1, b1, c1, X[ 5], 6, k3); + Subround(I, c1, d1, a1, b1, X[ 6], 5, k3); + Subround(I, b1, c1, d1, a1, X[ 2], 12, k3); + + Subround(I, a2, b2, c2, d2, X[ 5], 8, k5); + Subround(I, d2, a2, b2, c2, X[14], 9, k5); + Subround(I, c2, d2, a2, b2, X[ 7], 9, k5); + Subround(I, b2, c2, d2, a2, X[ 0], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 9], 13, k5); + Subround(I, d2, a2, b2, c2, X[ 2], 15, k5); + Subround(I, c2, d2, a2, b2, X[11], 15, k5); + Subround(I, b2, c2, d2, a2, X[ 4], 5, k5); + Subround(I, a2, b2, c2, d2, X[13], 7, k5); + Subround(I, d2, a2, b2, c2, X[ 6], 7, k5); + Subround(I, c2, d2, a2, b2, X[15], 8, k5); + Subround(I, b2, c2, d2, a2, X[ 8], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 1], 14, k5); + Subround(I, d2, a2, b2, c2, X[10], 14, k5); + Subround(I, c2, d2, a2, b2, X[ 3], 12, k5); + Subround(I, b2, c2, d2, a2, X[12], 6, k5); + + Subround(H, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(H, d2, a2, b2, c2, X[11], 13, k6); + Subround(H, c2, d2, a2, b2, X[ 3], 15, k6); + Subround(H, b2, c2, d2, a2, X[ 7], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 0], 12, k6); + Subround(H, d2, a2, b2, c2, X[13], 8, k6); + Subround(H, c2, d2, a2, b2, X[ 5], 9, k6); + Subround(H, b2, c2, d2, a2, X[10], 11, k6); + Subround(H, a2, b2, c2, d2, X[14], 7, k6); + Subround(H, d2, a2, b2, c2, X[15], 7, k6); + Subround(H, c2, d2, a2, b2, X[ 8], 12, k6); + Subround(H, b2, c2, d2, a2, X[12], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 4], 6, k6); + Subround(H, d2, a2, b2, c2, X[ 9], 15, k6); + Subround(H, c2, d2, a2, b2, X[ 1], 13, k6); + Subround(H, b2, c2, d2, a2, X[ 2], 11, k6); + + Subround(G, a2, b2, c2, d2, X[15], 9, k7); + Subround(G, d2, a2, b2, c2, X[ 5], 7, k7); + Subround(G, c2, d2, a2, b2, X[ 1], 15, k7); + Subround(G, b2, c2, d2, a2, X[ 3], 11, k7); + Subround(G, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(G, d2, a2, b2, c2, X[14], 6, k7); + Subround(G, c2, d2, a2, b2, X[ 6], 6, k7); + Subround(G, b2, c2, d2, a2, X[ 9], 14, k7); + Subround(G, a2, b2, c2, d2, X[11], 12, k7); + Subround(G, d2, a2, b2, c2, X[ 8], 13, k7); + Subround(G, c2, d2, a2, b2, X[12], 5, k7); + Subround(G, b2, c2, d2, a2, X[ 2], 14, k7); + Subround(G, a2, b2, c2, d2, X[10], 13, k7); + Subround(G, d2, a2, b2, c2, X[ 0], 13, k7); + Subround(G, c2, d2, a2, b2, X[ 4], 7, k7); + Subround(G, b2, c2, d2, a2, X[13], 5, k7); + + Subround(F, a2, b2, c2, d2, X[ 8], 15, k9); + Subround(F, d2, a2, b2, c2, X[ 6], 5, k9); + Subround(F, c2, d2, a2, b2, X[ 4], 8, k9); + Subround(F, b2, c2, d2, a2, X[ 1], 11, k9); + Subround(F, a2, b2, c2, d2, X[ 3], 14, k9); + Subround(F, d2, a2, b2, c2, X[11], 14, k9); + Subround(F, c2, d2, a2, b2, X[15], 6, k9); + Subround(F, b2, c2, d2, a2, X[ 0], 14, k9); + Subround(F, a2, b2, c2, d2, X[ 5], 6, k9); + Subround(F, d2, a2, b2, c2, X[12], 9, k9); + Subround(F, c2, d2, a2, b2, X[ 2], 12, k9); + Subround(F, b2, c2, d2, a2, X[13], 9, k9); + Subround(F, a2, b2, c2, d2, X[ 9], 12, k9); + Subround(F, d2, a2, b2, c2, X[ 7], 5, k9); + Subround(F, c2, d2, a2, b2, X[10], 15, k9); + Subround(F, b2, c2, d2, a2, X[14], 8, k9); + + c1 = digest[1] + c1 + d2; + digest[1] = digest[2] + d1 + a2; + digest[2] = digest[3] + a1 + b2; + digest[3] = digest[0] + b1 + c2; + digest[0] = c1; +} + +// ************************************************************* + +void RIPEMD256::Init() +{ + m_digest[0] = 0x67452301L; + m_digest[1] = 0xefcdab89L; + m_digest[2] = 0x98badcfeL; + m_digest[3] = 0x10325476L; + m_digest[4] = 0x76543210L; + m_digest[5] = 0xfedcba98L; + m_digest[6] = 0x89abcdefL; + m_digest[7] = 0x01234567L; +} + +void RIPEMD256::Transform (word32 *digest, const word32 *X) +{ + unsigned long a1, b1, c1, d1, a2, b2, c2, d2, t; + a1 = digest[0]; + b1 = digest[1]; + c1 = digest[2]; + d1 = digest[3]; + a2 = digest[4]; + b2 = digest[5]; + c2 = digest[6]; + d2 = digest[7]; + + Subround(F, a1, b1, c1, d1, X[ 0], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 1], 14, k0); + Subround(F, c1, d1, a1, b1, X[ 2], 15, k0); + Subround(F, b1, c1, d1, a1, X[ 3], 12, k0); + Subround(F, a1, b1, c1, d1, X[ 4], 5, k0); + Subround(F, d1, a1, b1, c1, X[ 5], 8, k0); + Subround(F, c1, d1, a1, b1, X[ 6], 7, k0); + Subround(F, b1, c1, d1, a1, X[ 7], 9, k0); + Subround(F, a1, b1, c1, d1, X[ 8], 11, k0); + Subround(F, d1, a1, b1, c1, X[ 9], 13, k0); + Subround(F, c1, d1, a1, b1, X[10], 14, k0); + Subround(F, b1, c1, d1, a1, X[11], 15, k0); + Subround(F, a1, b1, c1, d1, X[12], 6, k0); + Subround(F, d1, a1, b1, c1, X[13], 7, k0); + Subround(F, c1, d1, a1, b1, X[14], 9, k0); + Subround(F, b1, c1, d1, a1, X[15], 8, k0); + + Subround(I, a2, b2, c2, d2, X[ 5], 8, k5); + Subround(I, d2, a2, b2, c2, X[14], 9, k5); + Subround(I, c2, d2, a2, b2, X[ 7], 9, k5); + Subround(I, b2, c2, d2, a2, X[ 0], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 9], 13, k5); + Subround(I, d2, a2, b2, c2, X[ 2], 15, k5); + Subround(I, c2, d2, a2, b2, X[11], 15, k5); + Subround(I, b2, c2, d2, a2, X[ 4], 5, k5); + Subround(I, a2, b2, c2, d2, X[13], 7, k5); + Subround(I, d2, a2, b2, c2, X[ 6], 7, k5); + Subround(I, c2, d2, a2, b2, X[15], 8, k5); + Subround(I, b2, c2, d2, a2, X[ 8], 11, k5); + Subround(I, a2, b2, c2, d2, X[ 1], 14, k5); + Subround(I, d2, a2, b2, c2, X[10], 14, k5); + Subround(I, c2, d2, a2, b2, X[ 3], 12, k5); + Subround(I, b2, c2, d2, a2, X[12], 6, k5); + + t = a1; a1 = a2; a2 = t; + + Subround(G, a1, b1, c1, d1, X[ 7], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 4], 6, k1); + Subround(G, c1, d1, a1, b1, X[13], 8, k1); + Subround(G, b1, c1, d1, a1, X[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, X[10], 11, k1); + Subround(G, d1, a1, b1, c1, X[ 6], 9, k1); + Subround(G, c1, d1, a1, b1, X[15], 7, k1); + Subround(G, b1, c1, d1, a1, X[ 3], 15, k1); + Subround(G, a1, b1, c1, d1, X[12], 7, k1); + Subround(G, d1, a1, b1, c1, X[ 0], 12, k1); + Subround(G, c1, d1, a1, b1, X[ 9], 15, k1); + Subround(G, b1, c1, d1, a1, X[ 5], 9, k1); + Subround(G, a1, b1, c1, d1, X[ 2], 11, k1); + Subround(G, d1, a1, b1, c1, X[14], 7, k1); + Subround(G, c1, d1, a1, b1, X[11], 13, k1); + Subround(G, b1, c1, d1, a1, X[ 8], 12, k1); + + Subround(H, a2, b2, c2, d2, X[ 6], 9, k6); + Subround(H, d2, a2, b2, c2, X[11], 13, k6); + Subround(H, c2, d2, a2, b2, X[ 3], 15, k6); + Subround(H, b2, c2, d2, a2, X[ 7], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 0], 12, k6); + Subround(H, d2, a2, b2, c2, X[13], 8, k6); + Subround(H, c2, d2, a2, b2, X[ 5], 9, k6); + Subround(H, b2, c2, d2, a2, X[10], 11, k6); + Subround(H, a2, b2, c2, d2, X[14], 7, k6); + Subround(H, d2, a2, b2, c2, X[15], 7, k6); + Subround(H, c2, d2, a2, b2, X[ 8], 12, k6); + Subround(H, b2, c2, d2, a2, X[12], 7, k6); + Subround(H, a2, b2, c2, d2, X[ 4], 6, k6); + Subround(H, d2, a2, b2, c2, X[ 9], 15, k6); + Subround(H, c2, d2, a2, b2, X[ 1], 13, k6); + Subround(H, b2, c2, d2, a2, X[ 2], 11, k6); + + t = b1; b1 = b2; b2 = t; + + Subround(H, a1, b1, c1, d1, X[ 3], 11, k2); + Subround(H, d1, a1, b1, c1, X[10], 13, k2); + Subround(H, c1, d1, a1, b1, X[14], 6, k2); + Subround(H, b1, c1, d1, a1, X[ 4], 7, k2); + Subround(H, a1, b1, c1, d1, X[ 9], 14, k2); + Subround(H, d1, a1, b1, c1, X[15], 9, k2); + Subround(H, c1, d1, a1, b1, X[ 8], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, X[ 2], 14, k2); + Subround(H, d1, a1, b1, c1, X[ 7], 8, k2); + Subround(H, c1, d1, a1, b1, X[ 0], 13, k2); + Subround(H, b1, c1, d1, a1, X[ 6], 6, k2); + Subround(H, a1, b1, c1, d1, X[13], 5, k2); + Subround(H, d1, a1, b1, c1, X[11], 12, k2); + Subround(H, c1, d1, a1, b1, X[ 5], 7, k2); + Subround(H, b1, c1, d1, a1, X[12], 5, k2); + + Subround(G, a2, b2, c2, d2, X[15], 9, k7); + Subround(G, d2, a2, b2, c2, X[ 5], 7, k7); + Subround(G, c2, d2, a2, b2, X[ 1], 15, k7); + Subround(G, b2, c2, d2, a2, X[ 3], 11, k7); + Subround(G, a2, b2, c2, d2, X[ 7], 8, k7); + Subround(G, d2, a2, b2, c2, X[14], 6, k7); + Subround(G, c2, d2, a2, b2, X[ 6], 6, k7); + Subround(G, b2, c2, d2, a2, X[ 9], 14, k7); + Subround(G, a2, b2, c2, d2, X[11], 12, k7); + Subround(G, d2, a2, b2, c2, X[ 8], 13, k7); + Subround(G, c2, d2, a2, b2, X[12], 5, k7); + Subround(G, b2, c2, d2, a2, X[ 2], 14, k7); + Subround(G, a2, b2, c2, d2, X[10], 13, k7); + Subround(G, d2, a2, b2, c2, X[ 0], 13, k7); + Subround(G, c2, d2, a2, b2, X[ 4], 7, k7); + Subround(G, b2, c2, d2, a2, X[13], 5, k7); + + t = c1; c1 = c2; c2 = t; + + Subround(I, a1, b1, c1, d1, X[ 1], 11, k3); + Subround(I, d1, a1, b1, c1, X[ 9], 12, k3); + Subround(I, c1, d1, a1, b1, X[11], 14, k3); + Subround(I, b1, c1, d1, a1, X[10], 15, k3); + Subround(I, a1, b1, c1, d1, X[ 0], 14, k3); + Subround(I, d1, a1, b1, c1, X[ 8], 15, k3); + Subround(I, c1, d1, a1, b1, X[12], 9, k3); + Subround(I, b1, c1, d1, a1, X[ 4], 8, k3); + Subround(I, a1, b1, c1, d1, X[13], 9, k3); + Subround(I, d1, a1, b1, c1, X[ 3], 14, k3); + Subround(I, c1, d1, a1, b1, X[ 7], 5, k3); + Subround(I, b1, c1, d1, a1, X[15], 6, k3); + Subround(I, a1, b1, c1, d1, X[14], 8, k3); + Subround(I, d1, a1, b1, c1, X[ 5], 6, k3); + Subround(I, c1, d1, a1, b1, X[ 6], 5, k3); + Subround(I, b1, c1, d1, a1, X[ 2], 12, k3); + + Subround(F, a2, b2, c2, d2, X[ 8], 15, k9); + Subround(F, d2, a2, b2, c2, X[ 6], 5, k9); + Subround(F, c2, d2, a2, b2, X[ 4], 8, k9); + Subround(F, b2, c2, d2, a2, X[ 1], 11, k9); + Subround(F, a2, b2, c2, d2, X[ 3], 14, k9); + Subround(F, d2, a2, b2, c2, X[11], 14, k9); + Subround(F, c2, d2, a2, b2, X[15], 6, k9); + Subround(F, b2, c2, d2, a2, X[ 0], 14, k9); + Subround(F, a2, b2, c2, d2, X[ 5], 6, k9); + Subround(F, d2, a2, b2, c2, X[12], 9, k9); + Subround(F, c2, d2, a2, b2, X[ 2], 12, k9); + Subround(F, b2, c2, d2, a2, X[13], 9, k9); + Subround(F, a2, b2, c2, d2, X[ 9], 12, k9); + Subround(F, d2, a2, b2, c2, X[ 7], 5, k9); + Subround(F, c2, d2, a2, b2, X[10], 15, k9); + Subround(F, b2, c2, d2, a2, X[14], 8, k9); + + t = d1; d1 = d2; d2 = t; + + digest[0] += a1; + digest[1] += b1; + digest[2] += c1; + digest[3] += d1; + digest[4] += a2; + digest[5] += b2; + digest[6] += c2; + digest[7] += d2; +} + NAMESPACE_END @@ -19,6 +19,45 @@ protected: void Init(); }; +/*! Digest Length = 320 bits, Security = 160 bits */ +class RIPEMD320 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, RIPEMD320> +{ +public: + enum {DIGESTSIZE = 40}; + RIPEMD320() : IteratedHashWithStaticTransform<word32, LittleEndian, 64, RIPEMD320>(DIGESTSIZE) {Init();} + static void Transform(word32 *digest, const word32 *data); + static const char * StaticAlgorithmName() {return "RIPEMD-320";} + +protected: + void Init(); +}; + +/*! Digest Length = 128 bits */ +class RIPEMD128 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, RIPEMD128> +{ +public: + enum {DIGESTSIZE = 16}; + RIPEMD128() : IteratedHashWithStaticTransform<word32, LittleEndian, 64, RIPEMD128>(DIGESTSIZE) {Init();} + static void Transform(word32 *digest, const word32 *data); + static const char * StaticAlgorithmName() {return "RIPEMD-128";} + +protected: + void Init(); +}; + +/*! Digest Length = 256 bits, Security = 128 bits */ +class RIPEMD256 : public IteratedHashWithStaticTransform<word32, LittleEndian, 64, RIPEMD256> +{ +public: + enum {DIGESTSIZE = 32}; + RIPEMD256() : IteratedHashWithStaticTransform<word32, LittleEndian, 64, RIPEMD256>(DIGESTSIZE) {Init();} + static void Transform(word32 *digest, const word32 *data); + static const char * StaticAlgorithmName() {return "RIPEMD-256";} + +protected: + void Init(); +}; + NAMESPACE_END #endif @@ -116,22 +116,24 @@ MaurerRandomnessTest::MaurerRandomnessTest() tab[i] = 0; } -inline void MaurerRandomnessTest::Put(byte inByte) -{ - if (n >= Q) - sum += log(double(n - tab[inByte])); - tab[inByte] = n; - n++; -} - -void MaurerRandomnessTest::Put(const byte *inString, unsigned int length) +unsigned int MaurerRandomnessTest::Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking) { while (length--) - Put(*inString++); + { + byte inByte = *inString++; + if (n >= Q) + sum += log(double(n - tab[inByte])); + tab[inByte] = n; + n++; + } + return 0; } double MaurerRandomnessTest::GetTestValue() const { + if (BytesNeeded() > 0) + throw Exception(Exception::OTHER_ERROR, "MaurerRandomnessTest: " + IntToString(BytesNeeded()) + " more bytes of input needed"); + double fTu = (sum/(n-Q))/log(2.0); // this is the test value defined by Maurer double value = fTu * 0.1392; // arbitrarily normalize it to @@ -50,13 +50,12 @@ private: it is intended for measuring the randomness of *PHYSICAL* RNGs. For more details see his paper in Journal of Cryptology, 1992. */ -class MaurerRandomnessTest : public Sink +class MaurerRandomnessTest : public Bufferless<Sink> { public: MaurerRandomnessTest(); - void Put(byte inByte); - void Put(const byte *inString, unsigned int length); + unsigned int Put2(const byte *inString, unsigned int length, int messageEnd, bool blocking); // BytesNeeded() returns how many more bytes of input is needed by the test // GetTestValue() should not be called before BytesNeeded()==0 @@ -201,7 +201,14 @@ int main(int argc, char *argv[]) } } case 'm': - DigestFile(argv[2]); + if (command == "mt") + { + MaurerRandomnessTest mt; + FileStore(argv[2]).TransferAllTo(mt); + cout << "Maurer Test Value: " << mt.GetTestValue() << endl; + } + else + DigestFile(argv[2]); return 0; case 't': { @@ -547,7 +554,7 @@ void RSASignFile(const char *privFilename, const char *messageFilename, const ch FileSource privFile(privFilename, true, new HexDecoder); RSASSA_PKCS1v15_SHA_Signer priv(privFile); // RSASSA_PKCS1v15_SHA_Signer ignores the rng. Use a real RNG for other signature schemes! - FileSource f(messageFilename, true, new SignerFilter(NullRNG(), priv, new HexEncoder(new FileSink(signatureFilename)))); + FileSource f(messageFilename, true, new SignerFilter(GlobalRNG(), priv, new HexEncoder(new FileSink(signatureFilename)))); } bool RSAVerifyFile(const char *pubFilename, const char *messageFilename, const char *signatureFilename) @@ -922,6 +929,10 @@ bool Validate(int alg, bool thorough, const char *seed) case 57: result = ValidateESIGN(); break; case 58: result = ValidateDLIES(); break; case 59: result = ValidateBaseCode(); break; + case 60: result = ValidateSHACAL2(); break; + case 61: result = ValidateCamellia(); break; + case 62: result = ValidateWhirlpool(); break; + case 63: result = ValidateTTMAC(); break; default: result = ValidateAll(thorough); break; } @@ -59,6 +59,12 @@ Test Driver for Crypto++(TM) Library, a C++ Class Library of Cryptographic Schem - To run the FIPS 140-2 sample application cryptest fips +- To generate 100000 random files using FIPS Approved X.917 RNG + cryptest fips-rand + +- To run Maurer's randomness test on a file + cryptest mt input + - To run validation tests cryptest v diff --git a/validat1.cpp b/validat1.cpp index c71a0f4..ed3f26a 100644 --- a/validat1.cpp +++ b/validat1.cpp @@ -29,6 +29,8 @@ #include "twofish.h" #include "serpent.h" #include "skipjack.h" +#include "shacal2.h" +#include "camellia.h" #include "osrng.h" #include "zdeflate.h" @@ -58,10 +60,12 @@ bool ValidateAll(bool thorough) pass=ValidateTiger() && pass; pass=ValidateRIPEMD() && pass; pass=ValidatePanama() && pass; + pass=ValidateWhirlpool() && pass; pass=ValidateMD5MAC() && pass; pass=ValidateHMAC() && pass; pass=ValidateXMACC() && pass; + pass=ValidateTTMAC() && pass; pass=ValidatePBKDF() && pass; @@ -86,6 +90,8 @@ bool ValidateAll(bool thorough) pass=ValidateRijndael() && pass; pass=ValidateTwofish() && pass; pass=ValidateSerpent() && pass; + pass=ValidateSHACAL2() && pass; + pass=ValidateCamellia() && pass; pass=ValidateBBS() && pass; pass=ValidateDH() && pass; @@ -1308,3 +1314,31 @@ bool ValidateBaseCode() return pass; } + +bool ValidateSHACAL2() +{ + cout << "\nSHACAL-2 validation suite running...\n\n"; + + bool pass = true; + FileSource valdata("shacal2v.dat", true, new HexDecoder); + pass = BlockTransformationTest(FixedRoundsCipherFactory<SHACAL2Encryption, SHACAL2Decryption>(16), valdata, 4) && pass; + pass = BlockTransformationTest(FixedRoundsCipherFactory<SHACAL2Encryption, SHACAL2Decryption>(64), valdata, 10) && pass; + return pass; +} + +bool ValidateCamellia() +{ + cout << "\nCamellia validation suite running...\n\n"; + +#ifdef WORD64_AVAILABLE + bool pass = true; + FileSource valdata("camellia.dat", true, new HexDecoder); + pass = BlockTransformationTest(FixedRoundsCipherFactory<CamelliaEncryption, CamelliaDecryption>(16), valdata, 15) && pass; + pass = BlockTransformationTest(FixedRoundsCipherFactory<CamelliaEncryption, CamelliaDecryption>(24), valdata, 15) && pass; + pass = BlockTransformationTest(FixedRoundsCipherFactory<CamelliaEncryption, CamelliaDecryption>(32), valdata, 15) && pass; + return pass; +#else + cout << "word64 not available, skipping Camellia validation." << endl; + return true; +#endif +} diff --git a/validat3.cpp b/validat3.cpp index aa7aae1..e5ea465 100644 --- a/validat3.cpp +++ b/validat3.cpp @@ -14,10 +14,12 @@ #include "ripemd.h" #include "haval.h" #include "panama.h" +#include "whrlpool.h" #include "md5mac.h" #include "hmac.h" #include "xormac.h" +#include "ttmac.h" #include "integer.h" #include "pwdbased.h" @@ -189,31 +191,41 @@ bool ValidateSHA2() HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\x24\x8d\x6a\x61\xd2\x06\x38\xb8\xe5\xc0\x26\x93\x0c\x3e\x60\x39\xa3\x3c\xe4\x59\x64\xff\x21\x67\xf6\xec\xed\xd4\x19\xdb\x06\xc1"), }; + bool pass = true; + + cout << "\nSHA-256 validation suite running...\n\n"; + SHA256 sha256; + pass = HashModuleTest(sha256, testSet256, sizeof(testSet256)/sizeof(testSet256[0])) && pass; + + cout << "\nSHA-384 validation suite running...\n\n"; + +#ifdef WORD64_AVAILABLE HashTestTuple testSet384[] = { HashTestTuple("abc", "\xcb\x00\x75\x3f\x45\xa3\x5e\x8b\xb5\xa0\x3d\x69\x9a\xc6\x50\x07\x27\x2c\x32\xab\x0e\xde\xd1\x63\x1a\x8b\x60\x5a\x43\xff\x5b\xed\x80\x86\x07\x2b\xa1\xe7\xcc\x23\x58\xba\xec\xa1\x34\xc8\x25\xa7"), HashTestTuple("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "\x09\x33\x0c\x33\xf7\x11\x47\xe8\x3d\x19\x2f\xc7\x82\xcd\x1b\x47\x53\x11\x1b\x17\x3b\x3b\x05\xd2\x2f\xa0\x80\x86\xe3\xb0\xf7\x12\xfc\xc7\xc7\x1a\x55\x7e\x2d\xb9\x66\xc3\xe9\xfa\x91\x74\x60\x39"), }; + SHA384 sha384; + pass = HashModuleTest(sha384, testSet384, sizeof(testSet384)/sizeof(testSet384[0])) && pass; +#else + cout << "word64 not available, skipping SHA-384 validation." << endl; +#endif + + cout << "\nSHA-512 validation suite running...\n\n"; + +#ifdef WORD64_AVAILABLE HashTestTuple testSet512[] = { HashTestTuple("abc", "\xdd\xaf\x35\xa1\x93\x61\x7a\xba\xcc\x41\x73\x49\xae\x20\x41\x31\x12\xe6\xfa\x4e\x89\xa9\x7e\xa2\x0a\x9e\xee\xe6\x4b\x55\xd3\x9a\x21\x92\x99\x2a\x27\x4f\xc1\xa8\x36\xba\x3c\x23\xa3\xfe\xeb\xbd\x45\x4d\x44\x23\x64\x3c\xe8\x0e\x2a\x9a\xc9\x4f\xa5\x4c\xa4\x9f"), HashTestTuple("abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "\x8e\x95\x9b\x75\xda\xe3\x13\xda\x8c\xf4\xf7\x28\x14\xfc\x14\x3f\x8f\x77\x79\xc6\xeb\x9f\x7f\xa1\x72\x99\xae\xad\xb6\x88\x90\x18\x50\x1d\x28\x9e\x49\x00\xf7\xe4\x33\x1b\x99\xde\xc4\xb5\x43\x3a\xc7\xd3\x29\xee\xb6\xdd\x26\x54\x5e\x96\xe5\x5b\x87\x4b\xe9\x09"), }; - bool pass = true; - - cout << "\nSHA-256 validation suite running...\n\n"; - SHA256 sha256; - pass = HashModuleTest(sha256, testSet256, sizeof(testSet256)/sizeof(testSet256[0])) && pass; - - cout << "\nSHA-384 validation suite running...\n\n"; - SHA384 sha384; - pass = HashModuleTest(sha384, testSet384, sizeof(testSet384)/sizeof(testSet384[0])) && pass; - - cout << "\nSHA-512 validation suite running...\n\n"; SHA512 sha512; pass = HashModuleTest(sha512, testSet512, sizeof(testSet512)/sizeof(testSet512[0])) && pass; +#else + cout << "word64 not available, skipping SHA-512 validation." << endl; +#endif return pass; } @@ -247,7 +259,20 @@ bool ValidateTiger() bool ValidateRIPEMD() { - HashTestTuple testSet[] = + HashTestTuple testSet128[] = + { + HashTestTuple("", "\xcd\xf2\x62\x13\xa1\x50\xdc\x3e\xcb\x61\x0f\x18\xf6\xb3\x8b\x46"), + HashTestTuple("a", "\x86\xbe\x7a\xfa\x33\x9d\x0f\xc7\xcf\xc7\x85\xe7\x2f\x57\x8d\x33"), + HashTestTuple("abc", "\xc1\x4a\x12\x19\x9c\x66\xe4\xba\x84\x63\x6b\x0f\x69\x14\x4c\x77"), + HashTestTuple("message digest", "\x9e\x32\x7b\x3d\x6e\x52\x30\x62\xaf\xc1\x13\x2d\x7d\xf9\xd1\xb8"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xfd\x2a\xa6\x07\xf7\x1d\xc8\xf5\x10\x71\x49\x22\xb3\x71\x83\x4e"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\xa1\xaa\x06\x89\xd0\xfa\xfa\x2d\xdc\x22\xe8\x8b\x49\x13\x3a\x06"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xd1\xe9\x59\xeb\x17\x9c\x91\x1f\xae\xa4\x62\x4c\x60\xc5\xc7\x02"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x3f\x45\xef\x19\x47\x32\xc2\xdb\xb2\xc4\xa2\xc7\x69\x79\x5f\xa3"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x4a\x7f\x57\x23\xf9\x54\xeb\xa1\x21\x6c\x9d\x8f\x63\x20\x43\x1f", 15625) + }; + + HashTestTuple testSet160[] = { HashTestTuple("", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31"), HashTestTuple("a", "\x0b\xdc\x9d\x2d\x25\x6b\x3e\xe9\xda\xae\x34\x7b\xe6\xf4\xdc\x83\x5a\x46\x7f\xfe"), @@ -260,10 +285,51 @@ bool ValidateRIPEMD() HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\x52\x78\x32\x43\xc1\x69\x7b\xdb\xe1\x6d\x37\xf9\x7f\x68\xf0\x83\x25\xdc\x15\x28", 15625) }; - RIPEMD160 md; + HashTestTuple testSet256[] = + { + HashTestTuple("", "\x02\xba\x4c\x4e\x5f\x8e\xcd\x18\x77\xfc\x52\xd6\x4d\x30\xe3\x7a\x2d\x97\x74\xfb\x1e\x5d\x02\x63\x80\xae\x01\x68\xe3\xc5\x52\x2d"), + HashTestTuple("a", "\xf9\x33\x3e\x45\xd8\x57\xf5\xd9\x0a\x91\xba\xb7\x0a\x1e\xba\x0c\xfb\x1b\xe4\xb0\x78\x3c\x9a\xcf\xcd\x88\x3a\x91\x34\x69\x29\x25"), + HashTestTuple("abc", "\xaf\xbd\x6e\x22\x8b\x9d\x8c\xbb\xce\xf5\xca\x2d\x03\xe6\xdb\xa1\x0a\xc0\xbc\x7d\xcb\xe4\x68\x0e\x1e\x42\xd2\xe9\x75\x45\x9b\x65"), + HashTestTuple("message digest", "\x87\xe9\x71\x75\x9a\x1c\xe4\x7a\x51\x4d\x5c\x91\x4c\x39\x2c\x90\x18\xc7\xc4\x6b\xc1\x44\x65\x55\x4a\xfc\xdf\x54\xa5\x07\x0c\x0e"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\x64\x9d\x30\x34\x75\x1e\xa2\x16\x77\x6b\xf9\xa1\x8a\xcc\x81\xbc\x78\x96\x11\x8a\x51\x97\x96\x87\x82\xdd\x1f\xd9\x7d\x8d\x51\x33"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\x38\x43\x04\x55\x83\xaa\xc6\xc8\xc8\xd9\x12\x85\x73\xe7\xa9\x80\x9a\xfb\x2a\x0f\x34\xcc\xc3\x6e\xa9\xe7\x2f\x16\xf6\x36\x8e\x3f"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\x57\x40\xa4\x08\xac\x16\xb7\x20\xb8\x44\x24\xae\x93\x1c\xbb\x1f\xe3\x63\xd1\xd0\xbf\x40\x17\xf1\xa8\x9f\x7e\xa6\xde\x77\xa0\xb8"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x06\xfd\xcc\x7a\x40\x95\x48\xaa\xf9\x13\x68\xc0\x6a\x62\x75\xb5\x53\xe3\xf0\x99\xbf\x0e\xa4\xed\xfd\x67\x78\xdf\x89\xa8\x90\xdd"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xac\x95\x37\x44\xe1\x0e\x31\x51\x4c\x15\x0d\x4d\x8d\x7b\x67\x73\x42\xe3\x33\x99\x78\x82\x96\xe4\x3a\xe4\x85\x0c\xe4\xf9\x79\x78", 15625) + }; + + HashTestTuple testSet320[] = + { + HashTestTuple("", "\x22\xd6\x5d\x56\x61\x53\x6c\xdc\x75\xc1\xfd\xf5\xc6\xde\x7b\x41\xb9\xf2\x73\x25\xeb\xc6\x1e\x85\x57\x17\x7d\x70\x5a\x0e\xc8\x80\x15\x1c\x3a\x32\xa0\x08\x99\xb8"), + HashTestTuple("a", "\xce\x78\x85\x06\x38\xf9\x26\x58\xa5\xa5\x85\x09\x75\x79\x92\x6d\xda\x66\x7a\x57\x16\x56\x2c\xfc\xf6\xfb\xe7\x7f\x63\x54\x2f\x99\xb0\x47\x05\xd6\x97\x0d\xff\x5d"), + HashTestTuple("abc", "\xde\x4c\x01\xb3\x05\x4f\x89\x30\xa7\x9d\x09\xae\x73\x8e\x92\x30\x1e\x5a\x17\x08\x5b\xef\xfd\xc1\xb8\xd1\x16\x71\x3e\x74\xf8\x2f\xa9\x42\xd6\x4c\xdb\xc4\x68\x2d"), + HashTestTuple("message digest", "\x3a\x8e\x28\x50\x2e\xd4\x5d\x42\x2f\x68\x84\x4f\x9d\xd3\x16\xe7\xb9\x85\x33\xfa\x3f\x2a\x91\xd2\x9f\x84\xd4\x25\xc8\x8d\x6b\x4e\xff\x72\x7d\xf6\x6a\x7c\x01\x97"), + HashTestTuple("abcdefghijklmnopqrstuvwxyz", "\xca\xbd\xb1\x81\x0b\x92\x47\x0a\x20\x93\xaa\x6b\xce\x05\x95\x2c\x28\x34\x8c\xf4\x3f\xf6\x08\x41\x97\x51\x66\xbb\x40\xed\x23\x40\x04\xb8\x82\x44\x63\xe6\xb0\x09"), + HashTestTuple("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", "\xd0\x34\xa7\x95\x0c\xf7\x22\x02\x1b\xa4\xb8\x4d\xf7\x69\xa5\xde\x20\x60\xe2\x59\xdf\x4c\x9b\xb4\xa4\x26\x8c\x0e\x93\x5b\xbc\x74\x70\xa9\x69\xc9\xd0\x72\xa1\xac"), + HashTestTuple("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", "\xed\x54\x49\x40\xc8\x6d\x67\xf2\x50\xd2\x32\xc3\x0b\x7b\x3e\x57\x70\xe0\xc6\x0c\x8c\xb9\xa4\xca\xfe\x3b\x11\x38\x8a\xf9\x92\x0e\x1b\x99\x23\x0b\x84\x3c\x86\xa4"), + HashTestTuple("12345678901234567890123456789012345678901234567890123456789012345678901234567890", "\x55\x78\x88\xaf\x5f\x6d\x8e\xd6\x2a\xb6\x69\x45\xc6\xd2\xa0\xa4\x7e\xcd\x53\x41\xe9\x15\xeb\x8f\xea\x1d\x05\x24\x95\x5f\x82\x5d\xc7\x17\xe4\xa0\x08\xab\x2d\x42"), + HashTestTuple("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", "\xbd\xee\x37\xf4\x37\x1e\x20\x64\x6b\x8b\x0d\x86\x2d\xda\x16\x29\x2a\xe3\x6f\x40\x96\x5e\x8c\x85\x09\xe6\x3d\x1d\xbd\xde\xcc\x50\x3e\x2b\x63\xeb\x92\x45\xbb\x66", 15625) + }; + + bool pass = true; + + cout << "\nRIPEMD-128 validation suite running...\n\n"; + RIPEMD128 md128; + pass = HashModuleTest(md128, testSet128, sizeof(testSet128)/sizeof(testSet128[0])) && pass; cout << "\nRIPEMD-160 validation suite running...\n\n"; - return HashModuleTest(md, testSet, sizeof(testSet)/sizeof(testSet[0])); + RIPEMD160 md160; + pass = HashModuleTest(md160, testSet160, sizeof(testSet160)/sizeof(testSet160[0])) && pass; + + cout << "\nRIPEMD-256 validation suite running...\n\n"; + RIPEMD256 md256; + pass = HashModuleTest(md256, testSet256, sizeof(testSet256)/sizeof(testSet256[0])) && pass; + + cout << "\nRIPEMD-320 validation suite running...\n\n"; + RIPEMD320 md320; + pass = HashModuleTest(md320, testSet320, sizeof(testSet320)/sizeof(testSet320[0])) && pass; + + return pass; } bool ValidateHAVAL() @@ -390,6 +456,62 @@ bool ValidatePanama() return pass; } +bool ValidateWhirlpool() +{ + cout << "\nWhirlpool Hash Function validation suite running...\n\n"; + +#ifdef WORD64_AVAILABLE + // Selected test vectors from the Whirlpool NESSIE submission. + + const char Output0[] = + "\x47\x0F\x04\x09\xAB\xAA\x44\x6E\x49\x66\x7D\x4E\xBE\x12\xA1\x43" + "\x87\xCE\xDB\xD1\x0D\xD1\x7B\x82\x43\xCA\xD5\x50\xA0\x89\xDC\x0F" + "\xEE\xA7\xAA\x40\xF6\xC2\xAA\xAB\x71\xC6\xEB\xD0\x76\xE4\x3C\x7C" + "\xFC\xA0\xAD\x32\x56\x78\x97\xDC\xB5\x96\x98\x61\x04\x9A\x0F\x5A"; + const char Output1[] = + "\xEB\xAA\x1D\xF2\xE9\x71\x13\xBE\x18\x7E\xB0\x30\x3C\x66\x0F\x6E" + "\x64\x3E\x2C\x09\x0E\xF2\xCD\xA9\xA2\xEA\x6D\xCF\x50\x02\x14\x7D" + "\x1D\x0E\x1E\x9D\x99\x6E\x87\x9C\xEF\x9D\x26\x89\x66\x30\xA5\xDB" + "\x33\x08\xD5\xA0\xDC\x23\x5B\x19\x9C\x38\x92\x3B\xE2\x25\x9E\x03"; + const char Output16[] = + "\x40\x23\x8F\x57\xB2\x7D\x07\x4F\x9C\x8D\x04\x3D\xBD\x27\x07\xC7" + "\x18\xFC\x34\x49\xCC\x1F\x49\x0C\xA2\xF3\x24\xDF\xEC\x48\xB0\x5A" + "\xE7\x2D\x02\x6D\x89\x1C\xC0\x80\xE6\x31\x1F\xC3\x2E\xCF\xFC\x30" + "\xF4\x23\xDA\x7E\x63\xE3\x98\x7C\xA0\xCD\x37\xBF\xFD\x97\xCA\x56"; + const char Output32[] = + "\x48\xCC\xE9\x1F\x62\xB6\xD9\x35\x13\x38\x30\x1D\xF1\x82\xF4\x6A" + "\xD0\x7B\xB7\xB2\x33\xC1\x19\xCA\x2C\x1F\xC2\x19\xFF\xF9\x49\x85" + "\x8D\x47\xE5\x0D\x69\x18\xEB\xDC\xDF\x5F\x82\x98\x05\xFB\x86\x07" + "\x22\x76\x35\x69\xE6\xAB\x73\x41\x05\x4C\x38\x9C\xE9\xD6\xEB\xAC"; + const char Output33[] = + "\x60\x4B\x8B\x59\x15\xA7\xD6\x21\x42\x78\xDF\x08\x13\x53\x1F\xF2" + "\x60\xE1\x46\x51\xEC\xAC\xEC\x57\x6F\x01\xC4\x05\x42\x8F\x8D\x55" + "\x45\xB7\xEA\x6E\x65\x75\x8E\x5E\x83\xA4\x29\xD8\x52\xF4\x8C\x16" + "\x50\x6B\xBF\x00\xB5\x28\x51\x9B\x14\x2A\x77\x45\xF8\x31\x84\xD4"; + const char Output64[] = + "\xA0\x72\x51\x3B\x2A\xA9\xE0\x72\x26\xBA\x01\xE7\xD5\xB2\xB6\x26" + "\xE3\x62\xB1\x40\x1E\x1A\xEC\xF1\x68\xB9\x53\x32\x42\xC0\x18\xFF" + "\xEA\x81\x83\x7F\x7B\xD1\x60\xD1\xD0\xA9\x64\x4C\x8E\xD6\x41\x50" + "\xE6\x40\x6D\x2C\x1B\x74\x56\x02\x4F\x10\x98\x53\x90\x81\xFC\x77"; + + HashTestTuple testSet[] = + { + HashTestTuple("", 0, Output0, 1), + HashTestTuple("\0", 1, Output1, 1), + HashTestTuple("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, Output16, 1), + HashTestTuple("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, Output32, 2), + HashTestTuple("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 33, Output33, 1), + HashTestTuple("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, Output64, 4), + }; + + Whirlpool whirlpool; + return HashModuleTest(whirlpool, testSet, sizeof(testSet)/sizeof(testSet[0])); +#else + cout << "word64 not available, skipping Whirlpool validation." << endl; + return true; +#endif + } + bool ValidateMD5MAC() { const byte keys[2][MD5MAC::KEYLENGTH]={ @@ -557,6 +679,54 @@ bool ValidateXMACC() return pass; } +bool ValidateTTMAC() +{ + const byte key[TTMAC::KEYLENGTH]={ + 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99, + 0xaa,0xbb,0xcc,0xdd,0xee,0xff,0x01,0x23,0x45,0x67}; + + const char *TestVals[8]={ + "", + "a", + "abc", + "message digest", + "abcdefghijklmnopqrstuvwxyz", + "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", + "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}; + + const byte output[8][TTMAC::DIGESTSIZE]={ + {0x2d,0xec,0x8e,0xd4,0xa0,0xfd,0x71,0x2e,0xd9,0xfb,0xf2,0xab,0x46,0x6e,0xc2,0xdf,0x21,0x21,0x5e,0x4a}, + {0x58,0x93,0xe3,0xe6,0xe3,0x06,0x70,0x4d,0xd7,0x7a,0xd6,0xe6,0xed,0x43,0x2c,0xde,0x32,0x1a,0x77,0x56}, + {0x70,0xbf,0xd1,0x02,0x97,0x97,0xa5,0xc1,0x6d,0xa5,0xb5,0x57,0xa1,0xf0,0xb2,0x77,0x9b,0x78,0x49,0x7e}, + {0x82,0x89,0xf4,0xf1,0x9f,0xfe,0x4f,0x2a,0xf7,0x37,0xde,0x4b,0xd7,0x1c,0x82,0x9d,0x93,0xa9,0x72,0xfa}, + {0x21,0x86,0xca,0x09,0xc5,0x53,0x31,0x98,0xb7,0x37,0x1f,0x24,0x52,0x73,0x50,0x4c,0xa9,0x2b,0xae,0x60}, + {0x8a,0x7b,0xf7,0x7a,0xef,0x62,0xa2,0x57,0x84,0x97,0xa2,0x7c,0x0d,0x65,0x18,0xa4,0x29,0xe7,0xc1,0x4d}, + {0x54,0xba,0xc3,0x92,0xa8,0x86,0x80,0x6d,0x16,0x95,0x56,0xfc,0xbb,0x67,0x89,0xb5,0x4f,0xb3,0x64,0xfb}, + {0x0c,0xed,0x2c,0x9f,0x8f,0x0d,0x9d,0x03,0x98,0x1a,0xb5,0xc8,0x18,0x4b,0xac,0x43,0xdd,0x54,0xc4,0x84}}; + + byte digest[TTMAC::DIGESTSIZE]; + bool pass=true, fail; + + cout << "\nTwo-Track-MAC validation suite running...\n"; + + TTMAC mac(key, sizeof(key)); + for (int k=0; k<sizeof(TestVals)/sizeof(TestVals[0]); k++) + { + mac.Update((byte *)TestVals[k], strlen(TestVals[k])); + mac.Final(digest); + fail = memcmp(digest, output[k], TTMAC::DIGESTSIZE) + || !mac.VerifyDigest(output[k], (byte *)TestVals[k], strlen(TestVals[k])); + pass = pass && !fail; + cout << (fail ? "FAILED " : "passed "); + for (int j=0;j<TTMAC::DIGESTSIZE;j++) + cout << setw(2) << setfill('0') << hex << (int)digest[j]; + cout << " \"" << TestVals[k] << '\"' << endl; + } + + return true; +} + struct PBKDF_TestTuple { byte purpose; @@ -20,10 +20,12 @@ bool ValidateHAVAL(); bool ValidateTiger(); bool ValidateRIPEMD(); bool ValidatePanama(); +bool ValidateWhirlpool(); bool ValidateMD5MAC(); bool ValidateHMAC(); bool ValidateXMACC(); +bool ValidateTTMAC(); bool ValidateCipherModes(); bool ValidatePBKDF(); @@ -49,6 +51,8 @@ bool ValidateMARS(); bool ValidateRijndael(); bool ValidateTwofish(); bool ValidateSerpent(); +bool ValidateSHACAL2(); +bool ValidateCamellia(); bool ValidateBBS(); bool ValidateDH(); |