integration phase
authorWladimir J. van der Laan <laanwj@gmail.com>
Sat, 14 May 2011 09:18:39 +0000 (11:18 +0200)
committerWladimir J. van der Laan <laanwj@gmail.com>
Sat, 14 May 2011 09:18:39 +0000 (11:18 +0200)
20 files changed:
bitcoin.pro
cryptopp/include/cryptopp/config.h [new file with mode: 0644]
cryptopp/include/cryptopp/cpu.h [new file with mode: 0644]
cryptopp/include/cryptopp/cryptlib.h [new file with mode: 0644]
cryptopp/include/cryptopp/iterhash.h [new file with mode: 0644]
cryptopp/include/cryptopp/misc.h [new file with mode: 0644]
cryptopp/include/cryptopp/pch.h [new file with mode: 0644]
cryptopp/include/cryptopp/secblock.h [new file with mode: 0644]
cryptopp/include/cryptopp/sha.h [new file with mode: 0644]
cryptopp/include/cryptopp/simple.h [new file with mode: 0644]
cryptopp/include/cryptopp/smartptr.h [new file with mode: 0644]
cryptopp/include/cryptopp/stdcpp.h [new file with mode: 0644]
cryptopp/src/cpu.cpp [new file with mode: 0644]
cryptopp/src/sha.cpp [new file with mode: 0644]
gui/include/bitcoinaddressvalidator.h
gui/src/bitcoinaddressvalidator.cpp
gui/src/sendcoinsdialog.cpp
lib/include/bignum.h
lib/include/uint256.h
lib/include/util.h

index 88b92bc..dd31f3e 100644 (file)
@@ -1,7 +1,7 @@
 TEMPLATE = app
 TARGET =
 DEPENDPATH += .
-INCLUDEPATH += gui/include lib/include
+INCLUDEPATH += gui/include lib/include cryptopp/include
 
 # Input
 HEADERS += gui/include/bitcoingui.h \
@@ -18,7 +18,18 @@ HEADERS += gui/include/bitcoingui.h \
     lib/include/bignum.h \
     lib/include/util.h \
     lib/include/uint256.h \
-    lib/include/serialize.h
+    lib/include/serialize.h \
+    cryptopp/include/cryptopp/stdcpp.h \
+    cryptopp/include/cryptopp/smartptr.h \
+    cryptopp/include/cryptopp/simple.h \
+    cryptopp/include/cryptopp/sha.h \
+    cryptopp/include/cryptopp/secblock.h \
+    cryptopp/include/cryptopp/pch.h \
+    cryptopp/include/cryptopp/misc.h \
+    cryptopp/include/cryptopp/iterhash.h \
+    cryptopp/include/cryptopp/cryptlib.h \
+    cryptopp/include/cryptopp/cpu.h \
+    cryptopp/include/cryptopp/config.h
 SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
     gui/src/transactiontablemodel.cpp \
     gui/src/addresstablemodel.cpp \
@@ -28,7 +39,9 @@ SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
     gui/src/addressbookdialog.cpp \
     gui/src/aboutdialog.cpp \
     gui/src/editaddressdialog.cpp \
-    gui/src/bitcoinaddressvalidator.cpp
+    gui/src/bitcoinaddressvalidator.cpp \
+    cryptopp/src/sha.cpp \
+    cryptopp/src/cpu.cpp
 
 RESOURCES += \
     gui/bitcoin.qrc
diff --git a/cryptopp/include/cryptopp/config.h b/cryptopp/include/cryptopp/config.h
new file mode 100644 (file)
index 0000000..0737027
--- /dev/null
@@ -0,0 +1,462 @@
+#ifndef CRYPTOPP_CONFIG_H
+#define CRYPTOPP_CONFIG_H
+
+//// Bitcoin: disable SSE2 on 32-bit
+#if !defined(_M_X64) && !defined(__x86_64__)
+#define CRYPTOPP_DISABLE_SSE2  1
+#endif
+//////////// end of Bitcoin changes
+
+
+// ***************** Important Settings ********************
+
+// define this if running on a big-endian CPU
+#if !defined(IS_LITTLE_ENDIAN) && (defined(__BIG_ENDIAN__) || defined(__sparc) || defined(__sparc__) || defined(__hppa__) || defined(__mips__) || (defined(__MWERKS__) && !defined(__INTEL__)))
+#      define IS_BIG_ENDIAN
+#endif
+
+// define this if running on a little-endian CPU
+// big endian will be assumed if IS_LITTLE_ENDIAN is not defined
+#ifndef IS_BIG_ENDIAN
+#      define IS_LITTLE_ENDIAN
+#endif
+
+// define this if you want to disable all OS-dependent features,
+// such as sockets and OS-provided random number generators
+// #define NO_OS_DEPENDENCE
+
+// Define this to use features provided by Microsoft's CryptoAPI.
+// Currently the only feature used is random number generation.
+// This macro will be ignored if NO_OS_DEPENDENCE is defined.
+#define USE_MS_CRYPTOAPI
+
+// Define this to 1 to enforce the requirement in FIPS 186-2 Change Notice 1 that only 1024 bit moduli be used
+#ifndef DSA_1024_BIT_MODULUS_ONLY
+#      define DSA_1024_BIT_MODULUS_ONLY 1
+#endif
+
+// ***************** Less Important Settings ***************
+
+// define this to retain (as much as possible) old deprecated function and class names
+// #define CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+
+#define GZIP_OS_CODE 0
+
+// Try this if your CPU has 256K internal cache or a slow multiply instruction
+// and you want a (possibly) faster IDEA implementation using log tables
+// #define IDEA_LARGECACHE
+
+// Define this if, for the linear congruential RNG, you want to use
+// the original constants as specified in S.K. Park and K.W. Miller's
+// CACM paper.
+// #define LCRNG_ORIGINAL_NUMBERS
+
+// choose which style of sockets to wrap (mostly useful for cygwin which has both)
+#define PREFER_BERKELEY_STYLE_SOCKETS
+// #define PREFER_WINDOWS_STYLE_SOCKETS
+
+// set the name of Rijndael cipher, was "Rijndael" before version 5.3
+#define CRYPTOPP_RIJNDAEL_NAME "AES"
+
+// ***************** Important Settings Again ********************
+// But the defaults should be ok.
+
+// namespace support is now required
+#ifdef NO_NAMESPACE
+#      error namespace support is now required
+#endif
+
+// Define this to workaround a Microsoft CryptoAPI bug where
+// each call to CryptAcquireContext causes a 100 KB memory leak.
+// Defining this will cause Crypto++ to make only one call to CryptAcquireContext.
+#define WORKAROUND_MS_BUG_Q258000
+
+#ifdef CRYPTOPP_DOXYGEN_PROCESSING
+// Avoid putting "CryptoPP::" in front of everything in Doxygen output
+#      define CryptoPP
+#      define NAMESPACE_BEGIN(x)
+#      define NAMESPACE_END
+// Get Doxygen to generate better documentation for these typedefs
+#      define DOCUMENTED_TYPEDEF(x, y) class y : public x {};
+#else
+#      define NAMESPACE_BEGIN(x) namespace x {
+#      define NAMESPACE_END }
+#      define DOCUMENTED_TYPEDEF(x, y) typedef x y;
+#endif
+#define ANONYMOUS_NAMESPACE_BEGIN namespace {
+#define USING_NAMESPACE(x) using namespace x;
+#define DOCUMENTED_NAMESPACE_BEGIN(x) namespace x {
+#define DOCUMENTED_NAMESPACE_END }
+
+// What is the type of the third parameter to bind?
+// For Unix, the new standard is ::socklen_t (typically unsigned int), and the old standard is int.
+// Unfortunately there is no way to tell whether or not socklen_t is defined.
+// To work around this, TYPE_OF_SOCKLEN_T is a macro so that you can change it from the makefile.
+#ifndef TYPE_OF_SOCKLEN_T
+#      if defined(_WIN32) || defined(__CYGWIN__)
+#              define TYPE_OF_SOCKLEN_T int
+#      else
+#              define TYPE_OF_SOCKLEN_T ::socklen_t
+#      endif
+#endif
+
+#if defined(__CYGWIN__) && defined(PREFER_WINDOWS_STYLE_SOCKETS)
+#      define __USE_W32_SOCKETS
+#endif
+
+typedef unsigned char byte;            // put in global namespace to avoid ambiguity with other byte typedefs
+
+NAMESPACE_BEGIN(CryptoPP)
+
+typedef unsigned short word16;
+typedef unsigned int word32;
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+       typedef unsigned __int64 word64;
+       #define W64LIT(x) x##ui64
+#else
+       typedef unsigned long long word64;
+       #define W64LIT(x) x##ULL
+#endif
+
+// define large word type, used for file offsets and such
+typedef word64 lword;
+const lword LWORD_MAX = W64LIT(0xffffffffffffffff);
+
+#ifdef __GNUC__
+       #define CRYPTOPP_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
+#endif
+
+// define hword, word, and dword. these are used for multiprecision integer arithmetic
+// Intel compiler won't have _umul128 until version 10.0. See http://softwarecommunity.intel.com/isn/Community/en-US/forums/thread/30231625.aspx
+#if (defined(_MSC_VER) && (!defined(__INTEL_COMPILER) || __INTEL_COMPILER >= 1000) && (defined(_M_X64) || defined(_M_IA64))) || (defined(__DECCXX) && defined(__alpha__)) || (defined(__INTEL_COMPILER) && defined(__x86_64__)) || (defined(__SUNPRO_CC) && defined(__x86_64__))
+       typedef word32 hword;
+       typedef word64 word;
+#else
+       #define CRYPTOPP_NATIVE_DWORD_AVAILABLE
+       #if defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || defined(__x86_64__) || defined(__mips64) || defined(__sparc64__)
+               #if defined(__GNUC__) && !defined(__INTEL_COMPILER) && !(CRYPTOPP_GCC_VERSION == 40001 && defined(__APPLE__)) && CRYPTOPP_GCC_VERSION >= 30400
+                       // GCC 4.0.1 on MacOS X is missing __umodti3 and __udivti3
+                       // mode(TI) division broken on amd64 with GCC earlier than GCC 3.4
+                       typedef word32 hword;
+                       typedef word64 word;
+                       typedef __uint128_t dword;
+                       typedef __uint128_t word128;
+                       #define CRYPTOPP_WORD128_AVAILABLE
+               #else
+                       // if we're here, it means we're on a 64-bit CPU but we don't have a way to obtain 128-bit multiplication results
+                       typedef word16 hword;
+                       typedef word32 word;
+                       typedef word64 dword;
+               #endif
+       #else
+               // being here means the native register size is probably 32 bits or less
+               #define CRYPTOPP_BOOL_SLOW_WORD64 1
+               typedef word16 hword;
+               typedef word32 word;
+               typedef word64 dword;
+       #endif
+#endif
+#ifndef CRYPTOPP_BOOL_SLOW_WORD64
+       #define CRYPTOPP_BOOL_SLOW_WORD64 0
+#endif
+
+const unsigned int WORD_SIZE = sizeof(word);
+const unsigned int WORD_BITS = WORD_SIZE * 8;
+
+NAMESPACE_END
+
+#ifndef CRYPTOPP_L1_CACHE_LINE_SIZE
+       // This should be a lower bound on the L1 cache line size. It's used for defense against timing attacks.
+       #if defined(_M_X64) || defined(__x86_64__)
+               #define CRYPTOPP_L1_CACHE_LINE_SIZE 64
+       #else
+               // L1 cache line size is 32 on Pentium III and earlier
+               #define CRYPTOPP_L1_CACHE_LINE_SIZE 32
+       #endif
+#endif
+
+#if defined(_MSC_VER)
+       #if _MSC_VER == 1200
+               #include <malloc.h>
+       #endif
+       #if _MSC_VER > 1200 || defined(_mm_free)
+               #define CRYPTOPP_MSVC6PP_OR_LATER               // VC 6 processor pack or later
+       #else
+               #define CRYPTOPP_MSVC6_NO_PP                    // VC 6 without processor pack
+       #endif
+#endif
+
+#ifndef CRYPTOPP_ALIGN_DATA
+       #if defined(CRYPTOPP_MSVC6PP_OR_LATER)
+               #define CRYPTOPP_ALIGN_DATA(x) __declspec(align(x))
+       #elif defined(__GNUC__)
+               #define CRYPTOPP_ALIGN_DATA(x) __attribute__((aligned(x)))
+       #else
+               #define CRYPTOPP_ALIGN_DATA(x)
+       #endif
+#endif
+
+#ifndef CRYPTOPP_SECTION_ALIGN16
+       #if defined(__GNUC__) && !defined(__APPLE__)
+               // the alignment attribute doesn't seem to work without this section attribute when -fdata-sections is turned on
+               #define CRYPTOPP_SECTION_ALIGN16 __attribute__((section ("CryptoPP_Align16")))
+       #else
+               #define CRYPTOPP_SECTION_ALIGN16
+       #endif
+#endif
+
+#if defined(_MSC_VER) || defined(__fastcall)
+       #define CRYPTOPP_FASTCALL __fastcall
+#else
+       #define CRYPTOPP_FASTCALL
+#endif
+
+// VC60 workaround: it doesn't allow typename in some places
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#define CPP_TYPENAME
+#else
+#define CPP_TYPENAME typename
+#endif
+
+// VC60 workaround: can't cast unsigned __int64 to float or double
+#if defined(_MSC_VER) && !defined(CRYPTOPP_MSVC6PP_OR_LATER)
+#define CRYPTOPP_VC6_INT64 (__int64)
+#else
+#define CRYPTOPP_VC6_INT64
+#endif
+
+#ifdef _MSC_VER
+#define CRYPTOPP_NO_VTABLE __declspec(novtable)
+#else
+#define CRYPTOPP_NO_VTABLE
+#endif
+
+#ifdef _MSC_VER
+       // 4231: nonstandard extension used : 'extern' before template explicit instantiation
+       // 4250: dominance
+       // 4251: member needs to have dll-interface
+       // 4275: base needs to have dll-interface
+       // 4660: explicitly instantiating a class that's already implicitly instantiated
+       // 4661: no suitable definition provided for explicit template instantiation request
+       // 4786: identifer was truncated in debug information
+       // 4355: 'this' : used in base member initializer list
+       // 4910: '__declspec(dllexport)' and 'extern' are incompatible on an explicit instantiation
+#      pragma warning(disable: 4231 4250 4251 4275 4660 4661 4786 4355 4910)
+#endif
+
+#ifdef __BORLANDC__
+// 8037: non-const function called for const object. needed to work around BCB2006 bug
+#      pragma warn -8037
+#endif
+
+#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__MWERKS__) || defined(_STLPORT_VERSION)
+#define CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#endif
+
+#ifndef CRYPTOPP_DISABLE_UNCAUGHT_EXCEPTION
+#define CRYPTOPP_UNCAUGHT_EXCEPTION_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_DISABLE_X86ASM         // for backwards compatibility: this macro had both meanings
+#define CRYPTOPP_DISABLE_ASM
+#define CRYPTOPP_DISABLE_SSE2
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && ((defined(_MSC_VER) && defined(_M_IX86)) || (defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))))
+       #define CRYPTOPP_X86_ASM_AVAILABLE
+
+       #if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || CRYPTOPP_GCC_VERSION >= 30300)
+               #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
+       #else
+               #define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 0
+       #endif
+
+       // SSSE3 was actually introduced in GNU as 2.17, which was released 6/23/2006, but we can't tell what version of binutils is installed.
+       // GCC 4.1.2 was released on 2/13/2007, so we'll use that as a proxy for the binutils version.
+       #if !defined(CRYPTOPP_DISABLE_SSSE3) && (_MSC_VER >= 1400 || CRYPTOPP_GCC_VERSION >= 40102)
+               #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 1
+       #else
+               #define CRYPTOPP_BOOL_SSSE3_ASM_AVAILABLE 0
+       #endif
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && defined(_MSC_VER) && defined(_M_X64)
+       #define CRYPTOPP_X64_MASM_AVAILABLE
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_ASM) && defined(__GNUC__) && defined(__x86_64__)
+       #define CRYPTOPP_X64_ASM_AVAILABLE
+#endif
+
+#if !defined(CRYPTOPP_DISABLE_SSE2) && (defined(CRYPTOPP_MSVC6PP_OR_LATER) || defined(__SSE2__))
+       #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 1
+#else
+       #define CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE 0
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+       #define CRYPTOPP_BOOL_ALIGN16_ENABLED 1
+#else
+       #define CRYPTOPP_BOOL_ALIGN16_ENABLED 0
+#endif
+
+// how to allocate 16-byte aligned memory (for SSE2)
+#if defined(CRYPTOPP_MSVC6PP_OR_LATER)
+       #define CRYPTOPP_MM_MALLOC_AVAILABLE
+#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+       #define CRYPTOPP_MALLOC_ALIGNMENT_IS_16
+#elif defined(__linux__) || defined(__sun__) || defined(__CYGWIN__)
+       #define CRYPTOPP_MEMALIGN_AVAILABLE
+#else
+       #define CRYPTOPP_NO_ALIGNED_ALLOC
+#endif
+
+// how to disable inlining
+#if defined(_MSC_VER) && _MSC_VER >= 1300
+#      define CRYPTOPP_NOINLINE_DOTDOTDOT
+#      define CRYPTOPP_NOINLINE __declspec(noinline)
+#elif defined(__GNUC__)
+#      define CRYPTOPP_NOINLINE_DOTDOTDOT
+#      define CRYPTOPP_NOINLINE __attribute__((noinline))
+#else
+#      define CRYPTOPP_NOINLINE_DOTDOTDOT ...
+#      define CRYPTOPP_NOINLINE 
+#endif
+
+// how to declare class constants
+#if (defined(_MSC_VER) && _MSC_VER <= 1300) || defined(__INTEL_COMPILER)
+#      define CRYPTOPP_CONSTANT(x) enum {x};
+#else
+#      define CRYPTOPP_CONSTANT(x) static const int x;
+#endif
+
+#if defined(_M_X64) || defined(__x86_64__)
+       #define CRYPTOPP_BOOL_X64 1
+#else
+       #define CRYPTOPP_BOOL_X64 0
+#endif
+
+// see http://predef.sourceforge.net/prearch.html
+#if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_X86_) || defined(__I86__) || defined(__INTEL__)
+       #define CRYPTOPP_BOOL_X86 1
+#else
+       #define CRYPTOPP_BOOL_X86 0
+#endif
+
+#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86 || defined(__powerpc__)
+       #define CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+#endif
+
+#define CRYPTOPP_VERSION 560
+
+// ***************** determine availability of OS features ********************
+
+#ifndef NO_OS_DEPENDENCE
+
+#if defined(_WIN32) || defined(__CYGWIN__)
+#define CRYPTOPP_WIN32_AVAILABLE
+#endif
+
+#if defined(__unix__) || defined(__MACH__) || defined(__NetBSD__) || defined(__sun)
+#define CRYPTOPP_UNIX_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) || defined(CRYPTOPP_UNIX_AVAILABLE)
+#      define HIGHRES_TIMER_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_UNIX_AVAILABLE
+#      define HAS_BERKELEY_STYLE_SOCKETS
+#endif
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+#      define HAS_WINDOWS_STYLE_SOCKETS
+#endif
+
+#if defined(HIGHRES_TIMER_AVAILABLE) && (defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(HAS_WINDOWS_STYLE_SOCKETS))
+#      define SOCKETS_AVAILABLE
+#endif
+
+#if defined(HAS_WINDOWS_STYLE_SOCKETS) && (!defined(HAS_BERKELEY_STYLE_SOCKETS) || defined(PREFER_WINDOWS_STYLE_SOCKETS))
+#      define USE_WINDOWS_STYLE_SOCKETS
+#else
+#      define USE_BERKELEY_STYLE_SOCKETS
+#endif
+
+#if defined(HIGHRES_TIMER_AVAILABLE) && defined(CRYPTOPP_WIN32_AVAILABLE) && !defined(USE_BERKELEY_STYLE_SOCKETS)
+#      define WINDOWS_PIPES_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_WIN32_AVAILABLE) && defined(USE_MS_CRYPTOAPI)
+#      define NONBLOCKING_RNG_AVAILABLE
+#      define OS_RNG_AVAILABLE
+#endif
+
+#if defined(CRYPTOPP_UNIX_AVAILABLE) || defined(CRYPTOPP_DOXYGEN_PROCESSING)
+#      define NONBLOCKING_RNG_AVAILABLE
+#      define BLOCKING_RNG_AVAILABLE
+#      define OS_RNG_AVAILABLE
+#      define HAS_PTHREADS
+#      define THREADS_AVAILABLE
+#endif
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+#      define HAS_WINTHREADS
+#      define THREADS_AVAILABLE
+#endif
+
+#endif // NO_OS_DEPENDENCE
+
+// ***************** DLL related ********************
+
+#ifdef CRYPTOPP_WIN32_AVAILABLE
+
+#ifdef CRYPTOPP_EXPORTS
+#define CRYPTOPP_IS_DLL
+#define CRYPTOPP_DLL __declspec(dllexport)
+#elif defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_IS_DLL
+#define CRYPTOPP_DLL __declspec(dllimport)
+#else
+#define CRYPTOPP_DLL
+#endif
+
+#define CRYPTOPP_API __cdecl
+
+#else  // CRYPTOPP_WIN32_AVAILABLE
+
+#define CRYPTOPP_DLL
+#define CRYPTOPP_API
+
+#endif // CRYPTOPP_WIN32_AVAILABLE
+
+#if defined(__MWERKS__)
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern class CRYPTOPP_DLL
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#define CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS extern template class CRYPTOPP_DLL
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_DLL_TEMPLATE_CLASS template class CRYPTOPP_DLL
+#else
+#define CRYPTOPP_DLL_TEMPLATE_CLASS CRYPTOPP_EXTERN_DLL_TEMPLATE_CLASS
+#endif
+
+#if defined(__MWERKS__)
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern class
+#elif defined(__BORLANDC__) || defined(__SUNPRO_CC)
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS template class
+#else
+#define CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS extern template class
+#endif
+
+#if defined(CRYPTOPP_MANUALLY_INSTANTIATE_TEMPLATES) && !defined(CRYPTOPP_EXPORTS)
+#define CRYPTOPP_STATIC_TEMPLATE_CLASS template class
+#else
+#define CRYPTOPP_STATIC_TEMPLATE_CLASS CRYPTOPP_EXTERN_STATIC_TEMPLATE_CLASS
+#endif
+
+#endif
diff --git a/cryptopp/include/cryptopp/cpu.h b/cryptopp/include/cryptopp/cpu.h
new file mode 100644 (file)
index 0000000..113b8a1
--- /dev/null
@@ -0,0 +1,263 @@
+#ifndef CRYPTOPP_CPU_H
+#define CRYPTOPP_CPU_H
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+
+#define CRYPTOPP_X86_ASM_AVAILABLE
+#define CRYPTOPP_BOOL_X64 1
+#define CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE 1
+#define NAMESPACE_END
+
+#else
+
+#include "cryptopp/config.h"
+
+#ifdef CRYPTOPP_MSVC6PP_OR_LATER
+       #include <emmintrin.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || (_MSC_VER >= 1400 && CRYPTOPP_BOOL_X64)
+
+#define CRYPTOPP_CPUID_AVAILABLE
+
+// these should not be used directly
+extern CRYPTOPP_DLL bool g_x86DetectionDone;
+extern CRYPTOPP_DLL bool g_hasSSE2;
+extern CRYPTOPP_DLL bool g_hasISSE;
+extern CRYPTOPP_DLL bool g_hasMMX;
+extern CRYPTOPP_DLL bool g_hasSSSE3;
+extern CRYPTOPP_DLL bool g_isP4;
+extern CRYPTOPP_DLL word32 g_cacheLineSize;
+CRYPTOPP_DLL void CRYPTOPP_API DetectX86Features();
+
+CRYPTOPP_DLL bool CRYPTOPP_API CpuId(word32 input, word32 *output);
+
+#if CRYPTOPP_BOOL_X64
+inline bool HasSSE2()  {return true;}
+inline bool HasISSE()  {return true;}
+inline bool HasMMX()   {return true;}
+#else
+
+inline bool HasSSE2()
+{
+       if (!g_x86DetectionDone)
+               DetectX86Features();
+       return g_hasSSE2;
+}
+
+inline bool HasISSE()
+{
+       if (!g_x86DetectionDone)
+               DetectX86Features();
+       return g_hasISSE;
+}
+
+inline bool HasMMX()
+{
+       if (!g_x86DetectionDone)
+               DetectX86Features();
+       return g_hasMMX;
+}
+
+#endif
+
+inline bool HasSSSE3()
+{
+       if (!g_x86DetectionDone)
+               DetectX86Features();
+       return g_hasSSSE3;
+}
+
+inline bool IsP4()
+{
+       if (!g_x86DetectionDone)
+               DetectX86Features();
+       return g_isP4;
+}
+
+inline int GetCacheLineSize()
+{
+       if (!g_x86DetectionDone)
+               DetectX86Features();
+       return g_cacheLineSize;
+}
+
+#else
+
+inline int GetCacheLineSize()
+{
+       return CRYPTOPP_L1_CACHE_LINE_SIZE;
+}
+
+inline bool HasSSSE3() {return false;}
+inline bool IsP4()             {return false;}
+
+// assume MMX and SSE2 if intrinsics are enabled
+#if CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE || CRYPTOPP_BOOL_X64
+inline bool HasSSE2()  {return true;}
+inline bool HasISSE()  {return true;}
+inline bool HasMMX()   {return true;}
+#else
+inline bool HasSSE2()  {return false;}
+inline bool HasISSE()  {return false;}
+inline bool HasMMX()   {return false;}
+#endif
+
+#endif         // #ifdef CRYPTOPP_X86_ASM_AVAILABLE || _MSC_VER >= 1400
+
+#endif
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+       #define AS1(x) x*newline*
+       #define AS2(x, y) x, y*newline*
+       #define AS3(x, y, z) x, y, z*newline*
+       #define ASS(x, y, a, b, c, d) x, y, a*64+b*16+c*4+d*newline*
+       #define ASL(x) label##x:*newline*
+       #define ASJ(x, y, z) x label##y*newline*
+       #define ASC(x, y) x label##y*newline*
+       #define AS_HEX(y) 0##y##h
+#elif defined(__GNUC__)
+       // define these in two steps to allow arguments to be expanded
+       #define GNU_AS1(x) #x ";"
+       #define GNU_AS2(x, y) #x ", " #y ";"
+       #define GNU_AS3(x, y, z) #x ", " #y ", " #z ";"
+       #define GNU_ASL(x) "\n" #x ":"
+       #define GNU_ASJ(x, y, z) #x " " #y #z ";"
+       #define AS1(x) GNU_AS1(x)
+       #define AS2(x, y) GNU_AS2(x, y)
+       #define AS3(x, y, z) GNU_AS3(x, y, z)
+       #define ASS(x, y, a, b, c, d) #x ", " #y ", " #a "*64+" #b "*16+" #c "*4+" #d ";"
+       #define ASL(x) GNU_ASL(x)
+       #define ASJ(x, y, z) GNU_ASJ(x, y, z)
+       #define ASC(x, y) #x " " #y ";"
+       #define CRYPTOPP_NAKED
+       #define AS_HEX(y) 0x##y
+#else
+       #define AS1(x) __asm {x}
+       #define AS2(x, y) __asm {x, y}
+       #define AS3(x, y, z) __asm {x, y, z}
+       #define ASS(x, y, a, b, c, d) __asm {x, y, _MM_SHUFFLE(a, b, c, d)}
+       #define ASL(x) __asm {label##x:}
+       #define ASJ(x, y, z) __asm {x label##y}
+       #define ASC(x, y) __asm {x label##y}
+       #define CRYPTOPP_NAKED __declspec(naked)
+       #define AS_HEX(y) 0x##y
+#endif
+
+#define IF0(y)
+#define IF1(y) y
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+#define ASM_MOD(x, y) ((x) MOD (y))
+#define XMMWORD_PTR XMMWORD PTR
+#else
+// GNU assembler doesn't seem to have mod operator
+#define ASM_MOD(x, y) ((x)-((x)/(y))*(y))
+// GAS 2.15 doesn't support XMMWORD PTR. it seems necessary only for MASM
+#define XMMWORD_PTR
+#endif
+
+#if CRYPTOPP_BOOL_X86
+       #define AS_REG_1 ecx
+       #define AS_REG_2 edx
+       #define AS_REG_3 esi
+       #define AS_REG_4 edi
+       #define AS_REG_5 eax
+       #define AS_REG_6 ebx
+       #define AS_REG_7 ebp
+       #define AS_REG_1d ecx
+       #define AS_REG_2d edx
+       #define AS_REG_3d esi
+       #define AS_REG_4d edi
+       #define AS_REG_5d eax
+       #define AS_REG_6d ebx
+       #define AS_REG_7d ebp
+       #define WORD_SZ 4
+       #define WORD_REG(x)     e##x
+       #define WORD_PTR DWORD PTR
+       #define AS_PUSH_IF86(x) AS1(push e##x)
+       #define AS_POP_IF86(x) AS1(pop e##x)
+       #define AS_JCXZ jecxz
+#elif CRYPTOPP_BOOL_X64
+       #ifdef CRYPTOPP_GENERATE_X64_MASM
+               #define AS_REG_1 rcx
+               #define AS_REG_2 rdx
+               #define AS_REG_3 r8
+               #define AS_REG_4 r9
+               #define AS_REG_5 rax
+               #define AS_REG_6 r10
+               #define AS_REG_7 r11
+               #define AS_REG_1d ecx
+               #define AS_REG_2d edx
+               #define AS_REG_3d r8d
+               #define AS_REG_4d r9d
+               #define AS_REG_5d eax
+               #define AS_REG_6d r10d
+               #define AS_REG_7d r11d
+       #else
+               #define AS_REG_1 rdi
+               #define AS_REG_2 rsi
+               #define AS_REG_3 rdx
+               #define AS_REG_4 rcx
+               #define AS_REG_5 r8
+               #define AS_REG_6 r9
+               #define AS_REG_7 r10
+               #define AS_REG_1d edi
+               #define AS_REG_2d esi
+               #define AS_REG_3d edx
+               #define AS_REG_4d ecx
+               #define AS_REG_5d r8d
+               #define AS_REG_6d r9d
+               #define AS_REG_7d r10d
+       #endif
+       #define WORD_SZ 8
+       #define WORD_REG(x)     r##x
+       #define WORD_PTR QWORD PTR
+       #define AS_PUSH_IF86(x)
+       #define AS_POP_IF86(x)
+       #define AS_JCXZ jrcxz
+#endif
+
+// helper macro for stream cipher output
+#define AS_XMM_OUTPUT4(labelPrefix, inputPtr, outputPtr, x0, x1, x2, x3, t, p0, p1, p2, p3, increment)\
+       AS2(    test    inputPtr, inputPtr)\
+       ASC(    jz,             labelPrefix##3)\
+       AS2(    test    inputPtr, 15)\
+       ASC(    jnz,    labelPrefix##7)\
+       AS2(    pxor    xmm##x0, [inputPtr+p0*16])\
+       AS2(    pxor    xmm##x1, [inputPtr+p1*16])\
+       AS2(    pxor    xmm##x2, [inputPtr+p2*16])\
+       AS2(    pxor    xmm##x3, [inputPtr+p3*16])\
+       AS2(    add             inputPtr, increment*16)\
+       ASC(    jmp,    labelPrefix##3)\
+       ASL(labelPrefix##7)\
+       AS2(    movdqu  xmm##t, [inputPtr+p0*16])\
+       AS2(    pxor    xmm##x0, xmm##t)\
+       AS2(    movdqu  xmm##t, [inputPtr+p1*16])\
+       AS2(    pxor    xmm##x1, xmm##t)\
+       AS2(    movdqu  xmm##t, [inputPtr+p2*16])\
+       AS2(    pxor    xmm##x2, xmm##t)\
+       AS2(    movdqu  xmm##t, [inputPtr+p3*16])\
+       AS2(    pxor    xmm##x3, xmm##t)\
+       AS2(    add             inputPtr, increment*16)\
+       ASL(labelPrefix##3)\
+       AS2(    test    outputPtr, 15)\
+       ASC(    jnz,    labelPrefix##8)\
+       AS2(    movdqa  [outputPtr+p0*16], xmm##x0)\
+       AS2(    movdqa  [outputPtr+p1*16], xmm##x1)\
+       AS2(    movdqa  [outputPtr+p2*16], xmm##x2)\
+       AS2(    movdqa  [outputPtr+p3*16], xmm##x3)\
+       ASC(    jmp,    labelPrefix##9)\
+       ASL(labelPrefix##8)\
+       AS2(    movdqu  [outputPtr+p0*16], xmm##x0)\
+       AS2(    movdqu  [outputPtr+p1*16], xmm##x1)\
+       AS2(    movdqu  [outputPtr+p2*16], xmm##x2)\
+       AS2(    movdqu  [outputPtr+p3*16], xmm##x3)\
+       ASL(labelPrefix##9)\
+       AS2(    add             outputPtr, increment*16)
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/cryptlib.h b/cryptopp/include/cryptopp/cryptlib.h
new file mode 100644 (file)
index 0000000..1461af7
--- /dev/null
@@ -0,0 +1,1668 @@
+// cryptlib.h - written and placed in the public domain by Wei Dai
+/*! \file
+       This file contains the declarations for the abstract base
+       classes that provide a uniform interface to this library.
+*/
+
+/*!    \mainpage Crypto++ Library 5.6.0 API Reference
+<dl>
+<dt>Abstract Base Classes<dd>
+       cryptlib.h
+<dt>Authenticated Encryption<dd>
+       AuthenticatedSymmetricCipherDocumentation
+<dt>Symmetric Ciphers<dd>
+       SymmetricCipherDocumentation
+<dt>Hash Functions<dd>
+       SHA1, SHA224, SHA256, SHA384, SHA512, Tiger, Whirlpool, RIPEMD160, RIPEMD320, RIPEMD128, RIPEMD256, Weak1::MD2, Weak1::MD4, Weak1::MD5
+<dt>Non-Cryptographic Checksums<dd>
+       CRC32, Adler32
+<dt>Message Authentication Codes<dd>
+       VMAC, HMAC, CBC_MAC, CMAC, DMAC, TTMAC, GCM (GMAC)
+<dt>Random Number Generators<dd>
+       NullRNG(), LC_RNG, RandomPool, BlockingRng, NonblockingRng, AutoSeededRandomPool, AutoSeededX917RNG, DefaultAutoSeededRNG
+<dt>Password-based Cryptography<dd>
+       PasswordBasedKeyDerivationFunction
+<dt>Public Key Cryptosystems<dd>
+       DLIES, ECIES, LUCES, RSAES, RabinES, LUC_IES
+<dt>Public Key Signature Schemes<dd>
+       DSA, GDSA, ECDSA, NR, ECNR, LUCSS, RSASS, RSASS_ISO, RabinSS, RWSS, ESIGN
+<dt>Key Agreement<dd>
+       #DH, DH2, #MQV, ECDH, ECMQV, XTR_DH
+<dt>Algebraic Structures<dd>
+       Integer, PolynomialMod2, PolynomialOver, RingOfPolynomialsOver,
+       ModularArithmetic, MontgomeryRepresentation, GFP2_ONB,
+       GF2NP, GF256, GF2_32, EC2N, ECP
+<dt>Secret Sharing and Information Dispersal<dd>
+       SecretSharing, SecretRecovery, InformationDispersal, InformationRecovery
+<dt>Compression<dd>
+       Deflator, Inflator, Gzip, Gunzip, ZlibCompressor, ZlibDecompressor
+<dt>Input Source Classes<dd>
+       StringSource, ArraySource, FileSource, SocketSource, WindowsPipeSource, RandomNumberSource
+<dt>Output Sink Classes<dd>
+       StringSinkTemplate, ArraySink, FileSink, SocketSink, WindowsPipeSink, RandomNumberSink
+<dt>Filter Wrappers<dd>
+       StreamTransformationFilter, HashFilter, HashVerificationFilter, SignerFilter, SignatureVerificationFilter
+<dt>Binary to Text Encoders and Decoders<dd>
+       HexEncoder, HexDecoder, Base64Encoder, Base64Decoder, Base32Encoder, Base32Decoder
+<dt>Wrappers for OS features<dd>
+       Timer, Socket, WindowsHandle, ThreadLocalStorage, ThreadUserTimer
+<dt>FIPS 140 related<dd>
+       fips140.h
+</dl>
+
+In the FIPS 140-2 validated DLL version of Crypto++, only the following implementation class are available.
+<dl>
+<dt>Block Ciphers<dd>
+       AES, DES_EDE2, DES_EDE3, SKIPJACK
+<dt>Cipher Modes (replace template parameter BC with one of the block ciphers above)<dd>
+       ECB_Mode\<BC\>, CTR_Mode\<BC\>, CBC_Mode\<BC\>, CFB_FIPS_Mode\<BC\>, OFB_Mode\<BC\>
+<dt>Hash Functions<dd>
+       SHA1, SHA224, SHA256, SHA384, SHA512
+<dt>Public Key Signature Schemes (replace template parameter H with one of the hash functions above)<dd>
+       RSASS\<PKCS1v15, H\>, RSASS\<PSS, H\>, RSASS_ISO\<H\>, RWSS\<P1363_EMSA2, H\>, DSA, ECDSA\<ECP, H\>, ECDSA\<EC2N, H\>
+<dt>Message Authentication Codes (replace template parameter H with one of the hash functions above)<dd>
+       HMAC\<H\>, CBC_MAC\<DES_EDE2\>, CBC_MAC\<DES_EDE3\>
+<dt>Random Number Generators<dd>
+       DefaultAutoSeededRNG (AutoSeededX917RNG\<AES\>)
+<dt>Key Agreement<dd>
+       #DH
+<dt>Public Key Cryptosystems<dd>
+       RSAES\<OAEP\<SHA1\> \>
+</dl>
+
+<p>This reference manual is a work in progress. Some classes are still lacking detailed descriptions.
+<p>Click <a href="CryptoPPRef.zip">here</a> to download a zip archive containing this manual.
+<p>Thanks to Ryan Phillips for providing the Doxygen configuration file
+and getting me started with this manual.
+*/
+
+#ifndef CRYPTOPP_CRYPTLIB_H
+#define CRYPTOPP_CRYPTLIB_H
+
+#include "cryptopp/config.h"
+#include "cryptopp/stdcpp.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// forward declarations
+class Integer;
+class RandomNumberGenerator;
+class BufferedTransformation;
+
+//! used to specify a direction for a cipher to operate in (encrypt or decrypt)
+enum CipherDir {ENCRYPTION, DECRYPTION};
+
+//! used to represent infinite time
+const unsigned long INFINITE_TIME = ULONG_MAX;
+
+// VC60 workaround: using enums as template parameters causes problems
+template <typename ENUM_TYPE, int VALUE>
+struct EnumToType
+{
+       static ENUM_TYPE ToEnum() {return (ENUM_TYPE)VALUE;}
+};
+
+enum ByteOrder {LITTLE_ENDIAN_ORDER = 0, BIG_ENDIAN_ORDER = 1};
+typedef EnumToType<ByteOrder, LITTLE_ENDIAN_ORDER> LittleEndian;
+typedef EnumToType<ByteOrder, BIG_ENDIAN_ORDER> BigEndian;
+
+//! base class for all exceptions thrown by Crypto++
+class CRYPTOPP_DLL Exception : public std::exception
+{
+public:
+       //! error types
+       enum ErrorType {
+               //! a method is not implemented
+               NOT_IMPLEMENTED,
+               //! invalid function argument
+               INVALID_ARGUMENT,
+               //! BufferedTransformation received a Flush(true) signal but can't flush buffers
+               CANNOT_FLUSH,
+               //! data integerity check (such as CRC or MAC) failed
+               DATA_INTEGRITY_CHECK_FAILED,
+               //! received input data that doesn't conform to expected format
+               INVALID_DATA_FORMAT,
+               //! error reading from input device or writing to output device
+               IO_ERROR,
+               //! some error not belong to any of the above categories
+               OTHER_ERROR
+       };
+
+       explicit Exception(ErrorType errorType, const std::string &s) : m_errorType(errorType), m_what(s) {}
+       virtual ~Exception() throw() {}
+       const char *what() const throw() {return (m_what.c_str());}
+       const std::string &GetWhat() const {return m_what;}
+       void SetWhat(const std::string &s) {m_what = s;}
+       ErrorType GetErrorType() const {return m_errorType;}
+       void SetErrorType(ErrorType errorType) {m_errorType = errorType;}
+
+private:
+       ErrorType m_errorType;
+       std::string m_what;
+};
+
+//! exception thrown when an invalid argument is detected
+class CRYPTOPP_DLL InvalidArgument : public Exception
+{
+public:
+       explicit InvalidArgument(const std::string &s) : Exception(INVALID_ARGUMENT, s) {}
+};
+
+//! exception thrown when input data is received that doesn't conform to expected format
+class CRYPTOPP_DLL InvalidDataFormat : public Exception
+{
+public:
+       explicit InvalidDataFormat(const std::string &s) : Exception(INVALID_DATA_FORMAT, s) {}
+};
+
+//! exception thrown by decryption filters when trying to decrypt an invalid ciphertext
+class CRYPTOPP_DLL InvalidCiphertext : public InvalidDataFormat
+{
+public:
+       explicit InvalidCiphertext(const std::string &s) : InvalidDataFormat(s) {}
+};
+
+//! exception thrown by a class if a non-implemented method is called
+class CRYPTOPP_DLL NotImplemented : public Exception
+{
+public:
+       explicit NotImplemented(const std::string &s) : Exception(NOT_IMPLEMENTED, s) {}
+};
+
+//! exception thrown by a class when Flush(true) is called but it can't completely flush its buffers
+class CRYPTOPP_DLL CannotFlush : public Exception
+{
+public:
+       explicit CannotFlush(const std::string &s) : Exception(CANNOT_FLUSH, s) {}
+};
+
+//! error reported by the operating system
+class CRYPTOPP_DLL OS_Error : public Exception
+{
+public:
+       OS_Error(ErrorType errorType, const std::string &s, const std::string& operation, int errorCode)
+               : Exception(errorType, s), m_operation(operation), m_errorCode(errorCode) {}
+       ~OS_Error() throw() {}
+
+       // the operating system API that reported the error
+       const std::string & GetOperation() const {return m_operation;}
+       // the error code return by the operating system
+       int GetErrorCode() const {return m_errorCode;}
+
+protected:
+       std::string m_operation;
+       int m_errorCode;
+};
+
+//! used to return decoding results
+struct CRYPTOPP_DLL DecodingResult
+{
+       explicit DecodingResult() : isValidCoding(false), messageLength(0) {}
+       explicit DecodingResult(size_t len) : isValidCoding(true), messageLength(len) {}
+
+       bool operator==(const DecodingResult &rhs) const {return isValidCoding == rhs.isValidCoding && messageLength == rhs.messageLength;}
+       bool operator!=(const DecodingResult &rhs) const {return !operator==(rhs);}
+
+       bool isValidCoding;
+       size_t messageLength;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+       operator size_t() const {return isValidCoding ? messageLength : 0;}
+#endif
+};
+
+//! interface for retrieving values given their names
+/*! \note This class is used to safely pass a variable number of arbitrarily typed arguments to functions
+       and to read values from keys and crypto parameters.
+       \note To obtain an object that implements NameValuePairs for the purpose of parameter
+       passing, use the MakeParameters() function.
+       \note To get a value from NameValuePairs, you need to know the name and the type of the value. 
+       Call GetValueNames() on a NameValuePairs object to obtain a list of value names that it supports.
+       Then look at the Name namespace documentation to see what the type of each value is, or
+       alternatively, call GetIntValue() with the value name, and if the type is not int, a
+       ValueTypeMismatch exception will be thrown and you can get the actual type from the exception object.
+*/
+class CRYPTOPP_NO_VTABLE NameValuePairs
+{
+public:
+       virtual ~NameValuePairs() {}
+
+       //! exception thrown when trying to retrieve a value using a different type than expected
+       class CRYPTOPP_DLL ValueTypeMismatch : public InvalidArgument
+       {
+       public:
+               ValueTypeMismatch(const std::string &name, const std::type_info &stored, const std::type_info &retrieving)
+                       : InvalidArgument("NameValuePairs: type mismatch for '" + name + "', stored '" + stored.name() + "', trying to retrieve '" + retrieving.name() + "'")
+                       , m_stored(stored), m_retrieving(retrieving) {}
+
+               const std::type_info & GetStoredTypeInfo() const {return m_stored;}
+               const std::type_info & GetRetrievingTypeInfo() const {return m_retrieving;}
+
+       private:
+               const std::type_info &m_stored;
+               const std::type_info &m_retrieving;
+       };
+
+       //! get a copy of this object or a subobject of it
+       template <class T>
+       bool GetThisObject(T &object) const
+       {
+               return GetValue((std::string("ThisObject:")+typeid(T).name()).c_str(), object);
+       }
+
+       //! get a pointer to this object, as a pointer to T
+       template <class T>
+       bool GetThisPointer(T *&p) const
+       {
+               return GetValue((std::string("ThisPointer:")+typeid(T).name()).c_str(), p);
+       }
+
+       //! get a named value, returns true if the name exists
+       template <class T>
+       bool GetValue(const char *name, T &value) const
+       {
+               return GetVoidValue(name, typeid(T), &value);
+       }
+
+       //! get a named value, returns the default if the name doesn't exist
+       template <class T>
+       T GetValueWithDefault(const char *name, T defaultValue) const
+       {
+               GetValue(name, defaultValue);
+               return defaultValue;
+       }
+
+       //! get a list of value names that can be retrieved
+       CRYPTOPP_DLL std::string GetValueNames() const
+               {std::string result; GetValue("ValueNames", result); return result;}
+
+       //! get a named value with type int
+       /*! used to ensure we don't accidentally try to get an unsigned int
+               or some other type when we mean int (which is the most common case) */
+       CRYPTOPP_DLL bool GetIntValue(const char *name, int &value) const
+               {return GetValue(name, value);}
+
+       //! get a named value with type int, with default
+       CRYPTOPP_DLL int GetIntValueWithDefault(const char *name, int defaultValue) const
+               {return GetValueWithDefault(name, defaultValue);}
+
+       //! used by derived classes to check for type mismatch
+       CRYPTOPP_DLL static void CRYPTOPP_API ThrowIfTypeMismatch(const char *name, const std::type_info &stored, const std::type_info &retrieving)
+               {if (stored != retrieving) throw ValueTypeMismatch(name, stored, retrieving);}
+
+       template <class T>
+       void GetRequiredParameter(const char *className, const char *name, T &value) const
+       {
+               if (!GetValue(name, value))
+                       throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'");
+       }
+
+       CRYPTOPP_DLL void GetRequiredIntParameter(const char *className, const char *name, int &value) const
+       {
+               if (!GetIntValue(name, value))
+                       throw InvalidArgument(std::string(className) + ": missing required parameter '" + name + "'");
+       }
+
+       //! to be implemented by derived classes, users should use one of the above functions instead
+       CRYPTOPP_DLL virtual bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const =0;
+};
+
+//! namespace containing value name definitions
+/*!    value names, types and semantics:
+
+       ThisObject:ClassName (ClassName, copy of this object or a subobject)
+       ThisPointer:ClassName (const ClassName *, pointer to this object or a subobject)
+*/
+DOCUMENTED_NAMESPACE_BEGIN(Name)
+// more names defined in argnames.h
+DOCUMENTED_NAMESPACE_END
+
+//! empty set of name-value pairs
+class CRYPTOPP_DLL NullNameValuePairs : public NameValuePairs
+{
+public:
+       bool GetVoidValue(const char *name, const std::type_info &valueType, void *pValue) const {return false;}
+};
+
+//! _
+extern CRYPTOPP_DLL const NullNameValuePairs g_nullNameValuePairs;
+
+// ********************************************************
+
+//! interface for cloning objects, this is not implemented by most classes yet
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Clonable
+{
+public:
+       virtual ~Clonable() {}
+       //! this is not implemented by most classes yet
+       virtual Clonable* Clone() const {throw NotImplemented("Clone() is not implemented yet.");}      // TODO: make this =0
+};
+
+//! interface for all crypto algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE Algorithm : public Clonable
+{
+public:
+       /*! When FIPS 140-2 compliance is enabled and checkSelfTestStatus == true,
+               this constructor throws SelfTestFailure if the self test hasn't been run or fails. */
+       Algorithm(bool checkSelfTestStatus = true);
+       //! returns name of this algorithm, not universally implemented yet
+       virtual std::string AlgorithmName() const {return "unknown";}
+};
+
+//! keying interface for crypto algorithms that take byte strings as keys
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyingInterface
+{
+public:
+       virtual ~SimpleKeyingInterface() {}
+
+       //! returns smallest valid key length in bytes */
+       virtual size_t MinKeyLength() const =0;
+       //! returns largest valid key length in bytes */
+       virtual size_t MaxKeyLength() const =0;
+       //! returns default (recommended) key length in bytes */
+       virtual size_t DefaultKeyLength() const =0;
+
+       //! returns the smallest valid key length in bytes that is >= min(n, GetMaxKeyLength())
+       virtual size_t GetValidKeyLength(size_t n) const =0;
+
+       //! returns whether n is a valid key length
+       virtual bool IsValidKeyLength(size_t n) const
+               {return n == GetValidKeyLength(n);}
+
+       //! set or reset the key of this object
+       /*! \param params is used to specify Rounds, BlockSize, etc. */
+       virtual void SetKey(const byte *key, size_t length, const NameValuePairs &params = g_nullNameValuePairs);
+
+       //! calls SetKey() with an NameValuePairs object that just specifies "Rounds"
+       void SetKeyWithRounds(const byte *key, size_t length, int rounds);
+
+       //! calls SetKey() with an NameValuePairs object that just specifies "IV"
+       void SetKeyWithIV(const byte *key, size_t length, const byte *iv, size_t ivLength);
+
+       //! calls SetKey() with an NameValuePairs object that just specifies "IV"
+       void SetKeyWithIV(const byte *key, size_t length, const byte *iv)
+               {SetKeyWithIV(key, length, iv, IVSize());}
+
+       enum IV_Requirement {UNIQUE_IV = 0, RANDOM_IV, UNPREDICTABLE_RANDOM_IV, INTERNALLY_GENERATED_IV, NOT_RESYNCHRONIZABLE};
+       //! returns the minimal requirement for secure IVs
+       virtual IV_Requirement IVRequirement() const =0;
+
+       //! returns whether this object can be resynchronized (i.e. supports initialization vectors)
+       /*! If this function returns true, and no IV is passed to SetKey() and CanUseStructuredIVs()==true, an IV of all 0's will be assumed. */
+       bool IsResynchronizable() const {return IVRequirement() < NOT_RESYNCHRONIZABLE;}
+       //! returns whether this object can use random IVs (in addition to ones returned by GetNextIV)
+       bool CanUseRandomIVs() const {return IVRequirement() <= UNPREDICTABLE_RANDOM_IV;}
+       //! returns whether this object can use random but possibly predictable IVs (in addition to ones returned by GetNextIV)
+       bool CanUsePredictableIVs() const {return IVRequirement() <= RANDOM_IV;}
+       //! returns whether this object can use structured IVs, for example a counter (in addition to ones returned by GetNextIV)
+       bool CanUseStructuredIVs() const {return IVRequirement() <= UNIQUE_IV;}
+
+       virtual unsigned int IVSize() const {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+       //! returns default length of IVs accepted by this object
+       unsigned int DefaultIVLength() const {return IVSize();}
+       //! returns minimal length of IVs accepted by this object
+       virtual unsigned int MinIVLength() const {return IVSize();}
+       //! returns maximal length of IVs accepted by this object
+       virtual unsigned int MaxIVLength() const {return IVSize();}
+       //! resynchronize with an IV. ivLength=-1 means use IVSize()
+       virtual void Resynchronize(const byte *iv, int ivLength=-1) {throw NotImplemented(GetAlgorithm().AlgorithmName() + ": this object doesn't support resynchronization");}
+       //! get a secure IV for the next message
+       /*! This method should be called after you finish encrypting one message and are ready to start the next one.
+               After calling it, you must call SetKey() or Resynchronize() before using this object again. 
+               This method is not implemented on decryption objects. */
+       virtual void GetNextIV(RandomNumberGenerator &rng, byte *IV);
+
+protected:
+       virtual const Algorithm & GetAlgorithm() const =0;
+       virtual void UncheckedSetKey(const byte *key, unsigned int length, const NameValuePairs &params) =0;
+
+       void ThrowIfInvalidKeyLength(size_t length);
+       void ThrowIfResynchronizable();                 // to be called when no IV is passed
+       void ThrowIfInvalidIV(const byte *iv);  // check for NULL IV if it can't be used
+       size_t ThrowIfInvalidIVLength(int size);
+       const byte * GetIVAndThrowIfInvalid(const NameValuePairs &params, size_t &size);
+       inline void AssertValidKeyLength(size_t length) const
+               {assert(IsValidKeyLength(length));}
+};
+
+//! interface for the data processing part of block ciphers
+
+/*! Classes derived from BlockTransformation are block ciphers
+       in ECB mode (for example the DES::Encryption class), which are stateless.
+       These classes should not be used directly, but only in combination with
+       a mode class (see CipherModeDocumentation in modes.h).
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockTransformation : public Algorithm
+{
+public:
+       //! encrypt or decrypt inBlock, xor with xorBlock, and write to outBlock
+       virtual void ProcessAndXorBlock(const byte *inBlock, const byte *xorBlock, byte *outBlock) const =0;
+
+       //! encrypt or decrypt one block
+       /*! \pre size of inBlock and outBlock == BlockSize() */
+       void ProcessBlock(const byte *inBlock, byte *outBlock) const
+               {ProcessAndXorBlock(inBlock, NULL, outBlock);}
+
+       //! encrypt or decrypt one block in place
+       void ProcessBlock(byte *inoutBlock) const
+               {ProcessAndXorBlock(inoutBlock, NULL, inoutBlock);}
+
+       //! block size of the cipher in bytes
+       virtual unsigned int BlockSize() const =0;
+
+       //! returns how inputs and outputs should be aligned for optimal performance
+       virtual unsigned int OptimalDataAlignment() const;
+
+       //! returns true if this is a permutation (i.e. there is an inverse transformation)
+       virtual bool IsPermutation() const {return true;}
+
+       //! returns true if this is an encryption object
+       virtual bool IsForwardTransformation() const =0;
+
+       //! return number of blocks that can be processed in parallel, for bit-slicing implementations
+       virtual unsigned int OptimalNumberOfParallelBlocks() const {return 1;}
+
+       enum {BT_InBlockIsCounter=1, BT_DontIncrementInOutPointers=2, BT_XorInput=4, BT_ReverseDirection=8} FlagsForAdvancedProcessBlocks;
+
+       //! encrypt and xor blocks according to flags (see FlagsForAdvancedProcessBlocks)
+       /*! /note If BT_InBlockIsCounter is set, last byte of inBlocks may be modified. */
+       virtual size_t AdvancedProcessBlocks(const byte *inBlocks, const byte *xorBlocks, byte *outBlocks, size_t length, word32 flags) const;
+
+       inline CipherDir GetCipherDirection() const {return IsForwardTransformation() ? ENCRYPTION : DECRYPTION;}
+};
+
+//! interface for the data processing part of stream ciphers
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE StreamTransformation : public Algorithm
+{
+public:
+       //! return a reference to this object, 
+       /*! This function is useful for passing a temporary StreamTransformation object to a 
+               function that takes a non-const reference. */
+       StreamTransformation& Ref() {return *this;}
+
+       //! returns block size, if input must be processed in blocks, otherwise 1
+       virtual unsigned int MandatoryBlockSize() const {return 1;}
+
+       //! returns the input block size that is most efficient for this cipher
+       /*! \note optimal input length is n * OptimalBlockSize() - GetOptimalBlockSizeUsed() for any n > 0 */
+       virtual unsigned int OptimalBlockSize() const {return MandatoryBlockSize();}
+       //! returns how much of the current block is used up
+       virtual unsigned int GetOptimalBlockSizeUsed() const {return 0;}
+
+       //! returns how input should be aligned for optimal performance
+       virtual unsigned int OptimalDataAlignment() const;
+
+       //! encrypt or decrypt an array of bytes of specified length
+       /*! \note either inString == outString, or they don't overlap */
+       virtual void ProcessData(byte *outString, const byte *inString, size_t length) =0;
+
+       //! for ciphers where the last block of data is special, encrypt or decrypt the last block of data
+       /*! For now the only use of this function is for CBC-CTS mode. */
+       virtual void ProcessLastBlock(byte *outString, const byte *inString, size_t length);
+       //! returns the minimum size of the last block, 0 indicating the last block is not special
+       virtual unsigned int MinLastBlockSize() const {return 0;}
+
+       //! same as ProcessData(inoutString, inoutString, length)
+       inline void ProcessString(byte *inoutString, size_t length)
+               {ProcessData(inoutString, inoutString, length);}
+       //! same as ProcessData(outString, inString, length)
+       inline void ProcessString(byte *outString, const byte *inString, size_t length)
+               {ProcessData(outString, inString, length);}
+       //! implemented as {ProcessData(&input, &input, 1); return input;}
+       inline byte ProcessByte(byte input)
+               {ProcessData(&input, &input, 1); return input;}
+
+       //! returns whether this cipher supports random access
+       virtual bool IsRandomAccess() const =0;
+       //! for random access ciphers, seek to an absolute position
+       virtual void Seek(lword n)
+       {
+               assert(!IsRandomAccess());
+               throw NotImplemented("StreamTransformation: this object doesn't support random access");
+       }
+
+       //! returns whether this transformation is self-inverting (e.g. xor with a keystream)
+       virtual bool IsSelfInverting() const =0;
+       //! returns whether this is an encryption object
+       virtual bool IsForwardTransformation() const =0;
+};
+
+//! interface for hash functions and data processing part of MACs
+
+/*! HashTransformation objects are stateful.  They are created in an initial state,
+       change state as Update() is called, and return to the initial
+       state when Final() is called.  This interface allows a large message to
+       be hashed in pieces by calling Update() on each piece followed by
+       calling Final().
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE HashTransformation : public Algorithm
+{
+public:
+       //! return a reference to this object, 
+       /*! This function is useful for passing a temporary HashTransformation object to a 
+               function that takes a non-const reference. */
+       HashTransformation& Ref() {return *this;}
+
+       //! process more input
+       virtual void Update(const byte *input, size_t length) =0;
+
+       //! request space to write input into
+       virtual byte * CreateUpdateSpace(size_t &size) {size=0; return NULL;}
+
+       //! compute hash for current message, then restart for a new message
+       /*!     \pre size of digest == DigestSize(). */
+       virtual void Final(byte *digest)
+               {TruncatedFinal(digest, DigestSize());}
+
+       //! discard the current state, and restart with a new message
+       virtual void Restart()
+               {TruncatedFinal(NULL, 0);}
+
+       //! size of the hash/digest/MAC returned by Final()
+       virtual unsigned int DigestSize() const =0;
+
+       //! same as DigestSize()
+       unsigned int TagSize() const {return DigestSize();}
+
+
+       //! block size of underlying compression function, or 0 if not block based
+       virtual unsigned int BlockSize() const {return 0;}
+
+       //! input to Update() should have length a multiple of this for optimal speed
+       virtual unsigned int OptimalBlockSize() const {return 1;}
+
+       //! returns how input should be aligned for optimal performance
+       virtual unsigned int OptimalDataAlignment() const;
+
+       //! use this if your input is in one piece and you don't want to call Update() and Final() separately
+       virtual void CalculateDigest(byte *digest, const byte *input, size_t length)
+               {Update(input, length); Final(digest);}
+
+       //! verify that digest is a valid digest for the current message, then reinitialize the object
+       /*! Default implementation is to call Final() and do a bitwise comparison
+               between its output and digest. */
+       virtual bool Verify(const byte *digest)
+               {return TruncatedVerify(digest, DigestSize());}
+
+       //! use this if your input is in one piece and you don't want to call Update() and Verify() separately
+       virtual bool VerifyDigest(const byte *digest, const byte *input, size_t length)
+               {Update(input, length); return Verify(digest);}
+
+       //! truncated version of Final()
+       virtual void TruncatedFinal(byte *digest, size_t digestSize) =0;
+
+       //! truncated version of CalculateDigest()
+       virtual void CalculateTruncatedDigest(byte *digest, size_t digestSize, const byte *input, size_t length)
+               {Update(input, length); TruncatedFinal(digest, digestSize);}
+
+       //! truncated version of Verify()
+       virtual bool TruncatedVerify(const byte *digest, size_t digestLength);
+
+       //! truncated version of VerifyDigest()
+       virtual bool VerifyTruncatedDigest(const byte *digest, size_t digestLength, const byte *input, size_t length)
+               {Update(input, length); return TruncatedVerify(digest, digestLength);}
+
+protected:
+       void ThrowIfInvalidTruncatedSize(size_t size) const;
+};
+
+typedef HashTransformation HashFunction;
+
+//! interface for one direction (encryption or decryption) of a block cipher
+/*! \note These objects usually should not be used directly. See BlockTransformation for more details. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BlockCipher : public SimpleKeyingInterface, public BlockTransformation
+{
+protected:
+       const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for one direction (encryption or decryption) of a stream cipher or cipher mode
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SymmetricCipher : public SimpleKeyingInterface, public StreamTransformation
+{
+protected:
+       const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for message authentication codes
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE MessageAuthenticationCode : public SimpleKeyingInterface, public HashTransformation
+{
+protected:
+       const Algorithm & GetAlgorithm() const {return *this;}
+};
+
+//! interface for for one direction (encryption or decryption) of a stream cipher or block cipher mode with authentication
+/*! The StreamTransformation part of this interface is used to encrypt/decrypt the data, and the MessageAuthenticationCode part of this
+       interface is used to input additional authenticated data (AAD, which is MAC'ed but not encrypted), and to generate/verify the MAC. */
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedSymmetricCipher : public MessageAuthenticationCode, public StreamTransformation
+{
+public:
+       //! this indicates that a member function was called in the wrong state, for example trying to encrypt a message before having set the key or IV
+       class BadState : public Exception
+       {
+       public:
+               explicit BadState(const std::string &name, const char *message) : Exception(OTHER_ERROR, name + ": " + message) {}
+               explicit BadState(const std::string &name, const char *function, const char *state) : Exception(OTHER_ERROR, name + ": " + function + " was called before " + state) {}
+       };
+
+       //! the maximum length of AAD that can be input before the encrypted data
+       virtual lword MaxHeaderLength() const =0;
+       //! the maximum length of encrypted data
+       virtual lword MaxMessageLength() const =0;
+       //! the maximum length of AAD that can be input after the encrypted data
+       virtual lword MaxFooterLength() const {return 0;}
+       //! if this function returns true, SpecifyDataLengths() must be called before attempting to input data
+       /*! This is the case for some schemes, such as CCM. */
+       virtual bool NeedsPrespecifiedDataLengths() const {return false;}
+       //! this function only needs to be called if NeedsPrespecifiedDataLengths() returns true
+       void SpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength=0);
+       //! encrypt and generate MAC in one call. will truncate MAC if macSize < TagSize()
+       virtual void EncryptAndAuthenticate(byte *ciphertext, byte *mac, size_t macSize, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *message, size_t messageLength);
+       //! decrypt and verify MAC in one call, returning true iff MAC is valid. will assume MAC is truncated if macLength < TagSize()
+       virtual bool DecryptAndVerify(byte *message, const byte *mac, size_t macLength, const byte *iv, int ivLength, const byte *header, size_t headerLength, const byte *ciphertext, size_t ciphertextLength);
+
+       // redeclare this to avoid compiler ambiguity errors
+       virtual std::string AlgorithmName() const =0;
+
+protected:
+       const Algorithm & GetAlgorithm() const {return *static_cast<const MessageAuthenticationCode *>(this);}
+       virtual void UncheckedSpecifyDataLengths(lword headerLength, lword messageLength, lword footerLength) {}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef SymmetricCipher StreamCipher;
+#endif
+
+//! interface for random number generators
+/*! All return values are uniformly distributed over the range specified.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE RandomNumberGenerator : public Algorithm
+{
+public:
+       //! update RNG state with additional unpredictable values
+       virtual void IncorporateEntropy(const byte *input, size_t length) {throw NotImplemented("RandomNumberGenerator: IncorporateEntropy not implemented");}
+
+       //! returns true if IncorporateEntropy is implemented
+       virtual bool CanIncorporateEntropy() const {return false;}
+
+       //! generate new random byte and return it
+       virtual byte GenerateByte();
+
+       //! generate new random bit and return it
+       /*! Default implementation is to call GenerateByte() and return its lowest bit. */
+       virtual unsigned int GenerateBit();
+
+       //! generate a random 32 bit word in the range min to max, inclusive
+       virtual word32 GenerateWord32(word32 a=0, word32 b=0xffffffffL);
+
+       //! generate random array of bytes
+       virtual void GenerateBlock(byte *output, size_t size);
+
+       //! generate and discard n bytes
+       virtual void DiscardBytes(size_t n);
+
+       //! generate random bytes as input to a BufferedTransformation
+       virtual void GenerateIntoBufferedTransformation(BufferedTransformation &target, const std::string &channel, lword length);
+
+       //! randomly shuffle the specified array, resulting permutation is uniformly distributed
+       template <class IT> void Shuffle(IT begin, IT end)
+       {
+               for (; begin != end; ++begin)
+                       std::iter_swap(begin, begin + GenerateWord32(0, end-begin-1));
+       }
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+       byte GetByte() {return GenerateByte();}
+       unsigned int GetBit() {return GenerateBit();}
+       word32 GetLong(word32 a=0, word32 b=0xffffffffL) {return GenerateWord32(a, b);}
+       word16 GetShort(word16 a=0, word16 b=0xffff) {return (word16)GenerateWord32(a, b);}
+       void GetBlock(byte *output, size_t size) {GenerateBlock(output, size);}
+#endif
+};
+
+//! returns a reference that can be passed to functions that ask for a RNG but doesn't actually use it
+CRYPTOPP_DLL RandomNumberGenerator & CRYPTOPP_API NullRNG();
+
+class WaitObjectContainer;
+class CallStack;
+
+//! interface for objects that you can wait for
+
+class CRYPTOPP_NO_VTABLE Waitable
+{
+public:
+       virtual ~Waitable() {}
+
+       //! maximum number of wait objects that this object can return
+       virtual unsigned int GetMaxWaitObjectCount() const =0;
+       //! put wait objects into container
+       /*! \param callStack is used for tracing no wait loops, example:
+                    something.GetWaitObjects(c, CallStack("my func after X", 0));
+                          - or in an outer GetWaitObjects() method that itself takes a callStack parameter:
+                            innerThing.GetWaitObjects(c, CallStack("MyClass::GetWaitObjects at X", &callStack)); */
+       virtual void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack) =0;
+       //! wait on this object
+       /*! same as creating an empty container, calling GetWaitObjects(), and calling Wait() on the container */
+       bool Wait(unsigned long milliseconds, CallStack const& callStack);
+};
+
+//! the default channel for BufferedTransformation, equal to the empty string
+extern CRYPTOPP_DLL const std::string DEFAULT_CHANNEL;
+
+//! channel for additional authenticated data, equal to "AAD"
+extern CRYPTOPP_DLL const std::string AAD_CHANNEL;
+
+//! interface for buffered transformations
+
+/*! BufferedTransformation is a generalization of BlockTransformation,
+       StreamTransformation, and HashTransformation.
+
+       A buffered transformation is an object that takes a stream of bytes
+       as input (this may be done in stages), does some computation on them, and
+       then places the result into an internal buffer for later retrieval.  Any
+       partial result already in the output buffer is not modified by further
+       input.
+
+       If a method takes a "blocking" parameter, and you
+       pass "false" for it, the method will return before all input has been processed if
+       the input cannot be processed without waiting (for network buffers to become available, for example).
+       In this case the method will return true
+       or a non-zero integer value. When this happens you must continue to call the method with the same
+       parameters until it returns false or zero, before calling any other method on it or
+       attached BufferedTransformation. The integer return value in this case is approximately
+       the number of bytes left to be processed, and can be used to implement a progress bar.
+
+       For functions that take a "propagation" parameter, propagation != 0 means pass on the signal to attached
+       BufferedTransformation objects, with propagation decremented at each step until it reaches 0.
+       -1 means unlimited propagation.
+
+       \nosubgrouping
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE BufferedTransformation : public Algorithm, public Waitable
+{
+public:
+       // placed up here for CW8
+       static const std::string &NULL_CHANNEL; // same as DEFAULT_CHANNEL, for backwards compatibility
+
+       BufferedTransformation() : Algorithm(false) {}
+
+       //! return a reference to this object
+       /*! This function is useful for passing a temporary BufferedTransformation object to a 
+               function that takes a non-const reference. */
+       BufferedTransformation& Ref() {return *this;}
+
+       //!     \name INPUT
+       //@{
+               //! input a byte for processing
+               size_t Put(byte inByte, bool blocking=true)
+                       {return Put(&inByte, 1, blocking);}
+               //! input multiple bytes
+               size_t Put(const byte *inString, size_t length, bool blocking=true)
+                       {return Put2(inString, length, 0, blocking);}
+
+               //! input a 16-bit word
+               size_t PutWord16(word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+               //! input a 32-bit word
+               size_t PutWord32(word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+
+               //! request space which can be written into by the caller, and then used as input to Put()
+               /*! \param size is requested size (as a hint) for input, and size of the returned space for output */
+               /*! \note The purpose of this method is to help avoid doing extra memory allocations. */
+               virtual byte * CreatePutSpace(size_t &size) {size=0; return NULL;}
+
+               virtual bool CanModifyInput() const {return false;}
+
+               //! input multiple bytes that may be modified by callee
+               size_t PutModifiable(byte *inString, size_t length, bool blocking=true)
+                       {return PutModifiable2(inString, length, 0, blocking);}
+
+               bool MessageEnd(int propagation=-1, bool blocking=true)
+                       {return !!Put2(NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);}
+               size_t PutMessageEnd(const byte *inString, size_t length, int propagation=-1, bool blocking=true)
+                       {return Put2(inString, length, propagation < 0 ? -1 : propagation+1, blocking);}
+
+               //! input multiple bytes for blocking or non-blocking processing
+               /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */
+               virtual size_t Put2(const byte *inString, size_t length, int messageEnd, bool blocking) =0;
+               //! input multiple bytes that may be modified by callee for blocking or non-blocking processing
+               /*! \param messageEnd means how many filters to signal MessageEnd to, including this one */
+               virtual size_t PutModifiable2(byte *inString, size_t length, int messageEnd, bool blocking)
+                       {return Put2(inString, length, messageEnd, blocking);}
+
+               //! thrown by objects that have not implemented nonblocking input processing
+               struct BlockingInputOnly : public NotImplemented
+                       {BlockingInputOnly(const std::string &s) : NotImplemented(s + ": Nonblocking input is not implemented by this object.") {}};
+       //@}
+
+       //!     \name WAITING
+       //@{
+               unsigned int GetMaxWaitObjectCount() const;
+               void GetWaitObjects(WaitObjectContainer &container, CallStack const& callStack);
+       //@}
+
+       //!     \name SIGNALS
+       //@{
+               virtual void IsolatedInitialize(const NameValuePairs &parameters) {throw NotImplemented("BufferedTransformation: this object can't be reinitialized");}
+               virtual bool IsolatedFlush(bool hardFlush, bool blocking) =0;
+               virtual bool IsolatedMessageSeriesEnd(bool blocking) {return false;}
+
+               //! initialize or reinitialize this object
+               virtual void Initialize(const NameValuePairs &parameters=g_nullNameValuePairs, int propagation=-1);
+               //! flush buffered input and/or output
+               /*! \param hardFlush is used to indicate whether all data should be flushed
+                       \note Hard flushes must be used with care. It means try to process and output everything, even if
+                       there may not be enough data to complete the action. For example, hard flushing a HexDecoder would
+                       cause an error if you do it after inputing an odd number of hex encoded characters.
+                       For some types of filters, for example ZlibDecompressor, hard flushes can only
+                       be done at "synchronization points". These synchronization points are positions in the data
+                       stream that are created by hard flushes on the corresponding reverse filters, in this
+                       example ZlibCompressor. This is useful when zlib compressed data is moved across a
+                       network in packets and compression state is preserved across packets, as in the ssh2 protocol.
+               */
+               virtual bool Flush(bool hardFlush, int propagation=-1, bool blocking=true);
+               //! mark end of a series of messages
+               /*! There should be a MessageEnd immediately before MessageSeriesEnd. */
+               virtual bool MessageSeriesEnd(int propagation=-1, bool blocking=true);
+
+               //! set propagation of automatically generated and transferred signals
+               /*! propagation == 0 means do not automaticly generate signals */
+               virtual void SetAutoSignalPropagation(int propagation) {}
+
+               //!
+               virtual int GetAutoSignalPropagation() const {return 0;}
+public:
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+               void Close() {MessageEnd();}
+#endif
+       //@}
+
+       //!     \name RETRIEVAL OF ONE MESSAGE
+       //@{
+               //! returns number of bytes that is currently ready for retrieval
+               /*! All retrieval functions return the actual number of bytes
+                       retrieved, which is the lesser of the request number and
+                       MaxRetrievable(). */
+               virtual lword MaxRetrievable() const;
+
+               //! returns whether any bytes are currently ready for retrieval
+               virtual bool AnyRetrievable() const;
+
+               //! try to retrieve a single byte
+               virtual size_t Get(byte &outByte);
+               //! try to retrieve multiple bytes
+               virtual size_t Get(byte *outString, size_t getMax);
+
+               //! peek at the next byte without removing it from the output buffer
+               virtual size_t Peek(byte &outByte) const;
+               //! peek at multiple bytes without removing them from the output buffer
+               virtual size_t Peek(byte *outString, size_t peekMax) const;
+
+               //! try to retrieve a 16-bit word
+               size_t GetWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER);
+               //! try to retrieve a 32-bit word
+               size_t GetWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER);
+
+               //! try to peek at a 16-bit word
+               size_t PeekWord16(word16 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
+               //! try to peek at a 32-bit word
+               size_t PeekWord32(word32 &value, ByteOrder order=BIG_ENDIAN_ORDER) const;
+
+               //! move transferMax bytes of the buffered output to target as input
+               lword TransferTo(BufferedTransformation &target, lword transferMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL)
+                       {TransferTo2(target, transferMax, channel); return transferMax;}
+
+               //! discard skipMax bytes from the output buffer
+               virtual lword Skip(lword skipMax=LWORD_MAX);
+
+               //! copy copyMax bytes of the buffered output to target as input
+               lword CopyTo(BufferedTransformation &target, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+                       {return CopyRangeTo(target, 0, copyMax, channel);}
+
+               //! copy copyMax bytes of the buffered output, starting at position (relative to current position), to target as input
+               lword CopyRangeTo(BufferedTransformation &target, lword position, lword copyMax=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL) const
+                       {lword i = position; CopyRangeTo2(target, i, i+copyMax, channel); return i-position;}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+               unsigned long MaxRetrieveable() const {return MaxRetrievable();}
+#endif
+       //@}
+
+       //!     \name RETRIEVAL OF MULTIPLE MESSAGES
+       //@{
+               //!
+               virtual lword TotalBytesRetrievable() const;
+               //! number of times MessageEnd() has been received minus messages retrieved or skipped
+               virtual unsigned int NumberOfMessages() const;
+               //! returns true if NumberOfMessages() > 0
+               virtual bool AnyMessages() const;
+               //! start retrieving the next message
+               /*!
+                       Returns false if no more messages exist or this message 
+                       is not completely retrieved.
+               */
+               virtual bool GetNextMessage();
+               //! skip count number of messages
+               virtual unsigned int SkipMessages(unsigned int count=UINT_MAX);
+               //!
+               unsigned int TransferMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL)
+                       {TransferMessagesTo2(target, count, channel); return count;}
+               //!
+               unsigned int CopyMessagesTo(BufferedTransformation &target, unsigned int count=UINT_MAX, const std::string &channel=DEFAULT_CHANNEL) const;
+
+               //!
+               virtual void SkipAll();
+               //!
+               void TransferAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
+                       {TransferAllTo2(target, channel);}
+               //!
+               void CopyAllTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const;
+
+               virtual bool GetNextMessageSeries() {return false;}
+               virtual unsigned int NumberOfMessagesInThisSeries() const {return NumberOfMessages();}
+               virtual unsigned int NumberOfMessageSeries() const {return 0;}
+       //@}
+
+       //!     \name NON-BLOCKING TRANSFER OF OUTPUT
+       //@{
+               //! upon return, byteCount contains number of bytes that have finished being transfered, and returns the number of bytes left in the current transfer block
+               virtual size_t TransferTo2(BufferedTransformation &target, lword &byteCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) =0;
+               //! upon return, begin contains the start position of data yet to be finished copying, and returns the number of bytes left in the current transfer block
+               virtual size_t CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end=LWORD_MAX, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true) const =0;
+               //! upon return, messageCount contains number of messages that have finished being transfered, and returns the number of bytes left in the current transfer block
+               size_t TransferMessagesTo2(BufferedTransformation &target, unsigned int &messageCount, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+               //! returns the number of bytes left in the current transfer block
+               size_t TransferAllTo2(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL, bool blocking=true);
+       //@}
+
+       //!     \name CHANNELS
+       //@{
+               struct NoChannelSupport : public NotImplemented
+                       {NoChannelSupport(const std::string &name) : NotImplemented(name + ": this object doesn't support multiple channels") {}};
+               struct InvalidChannelName : public InvalidArgument
+                       {InvalidChannelName(const std::string &name, const std::string &channel) : InvalidArgument(name + ": unexpected channel name \"" + channel + "\"") {}};
+
+               size_t ChannelPut(const std::string &channel, byte inByte, bool blocking=true)
+                       {return ChannelPut(channel, &inByte, 1, blocking);}
+               size_t ChannelPut(const std::string &channel, const byte *inString, size_t length, bool blocking=true)
+                       {return ChannelPut2(channel, inString, length, 0, blocking);}
+
+               size_t ChannelPutModifiable(const std::string &channel, byte *inString, size_t length, bool blocking=true)
+                       {return ChannelPutModifiable2(channel, inString, length, 0, blocking);}
+
+               size_t ChannelPutWord16(const std::string &channel, word16 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+               size_t ChannelPutWord32(const std::string &channel, word32 value, ByteOrder order=BIG_ENDIAN_ORDER, bool blocking=true);
+
+               bool ChannelMessageEnd(const std::string &channel, int propagation=-1, bool blocking=true)
+                       {return !!ChannelPut2(channel, NULL, 0, propagation < 0 ? -1 : propagation+1, blocking);}
+               size_t ChannelPutMessageEnd(const std::string &channel, const byte *inString, size_t length, int propagation=-1, bool blocking=true)
+                       {return ChannelPut2(channel, inString, length, propagation < 0 ? -1 : propagation+1, blocking);}
+
+               virtual byte * ChannelCreatePutSpace(const std::string &channel, size_t &size);
+
+               virtual size_t ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking);
+               virtual size_t ChannelPutModifiable2(const std::string &channel, byte *begin, size_t length, int messageEnd, bool blocking);
+
+               virtual bool ChannelFlush(const std::string &channel, bool hardFlush, int propagation=-1, bool blocking=true);
+               virtual bool ChannelMessageSeriesEnd(const std::string &channel, int propagation=-1, bool blocking=true);
+
+               virtual void SetRetrievalChannel(const std::string &channel);
+       //@}
+
+       //!     \name ATTACHMENT
+       /*! Some BufferedTransformation objects (e.g. Filter objects)
+               allow other BufferedTransformation objects to be attached. When
+               this is done, the first object instead of buffering its output,
+               sents that output to the attached object as input. The entire
+               attachment chain is deleted when the anchor object is destructed.
+       */
+       //@{
+               //! returns whether this object allows attachment
+               virtual bool Attachable() {return false;}
+               //! returns the object immediately attached to this object or NULL for no attachment
+               virtual BufferedTransformation *AttachedTransformation() {assert(!Attachable()); return 0;}
+               //!
+               virtual const BufferedTransformation *AttachedTransformation() const
+                       {return const_cast<BufferedTransformation *>(this)->AttachedTransformation();}
+               //! delete the current attachment chain and replace it with newAttachment
+               virtual void Detach(BufferedTransformation *newAttachment = 0)
+                       {assert(!Attachable()); throw NotImplemented("BufferedTransformation: this object is not attachable");}
+               //! add newAttachment to the end of attachment chain
+               virtual void Attach(BufferedTransformation *newAttachment);
+       //@}
+
+protected:
+       static int DecrementPropagation(int propagation)
+               {return propagation != 0 ? propagation - 1 : 0;}
+
+private:
+       byte m_buf[4];  // for ChannelPutWord16 and ChannelPutWord32, to ensure buffer isn't deallocated before non-blocking operation completes
+};
+
+//! returns a reference to a BufferedTransformation object that discards all input
+BufferedTransformation & TheBitBucket();
+
+//! interface for crypto material, such as public and private keys, and crypto parameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoMaterial : public NameValuePairs
+{
+public:
+       //! exception thrown when invalid crypto material is detected
+       class CRYPTOPP_DLL InvalidMaterial : public InvalidDataFormat
+       {
+       public:
+               explicit InvalidMaterial(const std::string &s) : InvalidDataFormat(s) {}
+       };
+
+       //! assign values from source to this object
+       /*! \note This function can be used to create a public key from a private key. */
+       virtual void AssignFrom(const NameValuePairs &source) =0;
+
+       //! check this object for errors
+       /*! \param level denotes the level of thoroughness:
+               0 - using this object won't cause a crash or exception (rng is ignored)
+               1 - this object will probably function (encrypt, sign, etc.) correctly (but may not check for weak keys and such)
+               2 - make sure this object will function correctly, and do reasonable security checks
+               3 - do checks that may take a long time
+               \return true if the tests pass */
+       virtual bool Validate(RandomNumberGenerator &rng, unsigned int level) const =0;
+
+       //! throws InvalidMaterial if this object fails Validate() test
+       virtual void ThrowIfInvalid(RandomNumberGenerator &rng, unsigned int level) const
+               {if (!Validate(rng, level)) throw InvalidMaterial("CryptoMaterial: this object contains invalid values");}
+
+//     virtual std::vector<std::string> GetSupportedFormats(bool includeSaveOnly=false, bool includeLoadOnly=false);
+
+       //! save key into a BufferedTransformation
+       virtual void Save(BufferedTransformation &bt) const
+               {throw NotImplemented("CryptoMaterial: this object does not support saving");}
+
+       //! load key from a BufferedTransformation
+       /*! \throws KeyingErr if decode fails
+               \note Generally does not check that the key is valid.
+                       Call ValidateKey() or ThrowIfInvalidKey() to check that. */
+       virtual void Load(BufferedTransformation &bt)
+               {throw NotImplemented("CryptoMaterial: this object does not support loading");}
+
+       //! \return whether this object supports precomputation
+       virtual bool SupportsPrecomputation() const {return false;}
+       //! do precomputation
+       /*! The exact semantics of Precompute() is varies, but
+               typically it means calculate a table of n objects
+               that can be used later to speed up computation. */
+       virtual void Precompute(unsigned int n)
+               {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+       //! retrieve previously saved precomputation
+       virtual void LoadPrecomputation(BufferedTransformation &storedPrecomputation)
+               {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+       //! save precomputation for later use
+       virtual void SavePrecomputation(BufferedTransformation &storedPrecomputation) const
+               {assert(!SupportsPrecomputation()); throw NotImplemented("CryptoMaterial: this object does not support precomputation");}
+
+       // for internal library use
+       void DoQuickSanityCheck() const {ThrowIfInvalid(NullRNG(), 0);}
+
+#if (defined(__SUNPRO_CC) && __SUNPRO_CC < 0x590)
+       // Sun Studio 11/CC 5.8 workaround: it generates incorrect code when casting to an empty virtual base class
+       char m_sunCCworkaround;
+#endif
+};
+
+//! interface for generatable crypto material, such as private keys and crypto parameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE GeneratableCryptoMaterial : virtual public CryptoMaterial
+{
+public:
+       //! generate a random key or crypto parameters
+       /*! \throws KeyingErr if algorithm parameters are invalid, or if a key can't be generated
+               (e.g., if this is a public key object) */
+       virtual void GenerateRandom(RandomNumberGenerator &rng, const NameValuePairs &params = g_nullNameValuePairs)
+               {throw NotImplemented("GeneratableCryptoMaterial: this object does not support key/parameter generation");}
+
+       //! calls the above function with a NameValuePairs object that just specifies "KeySize"
+       void GenerateRandomWithKeySize(RandomNumberGenerator &rng, unsigned int keySize);
+};
+
+//! interface for public keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKey : virtual public CryptoMaterial
+{
+};
+
+//! interface for private keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKey : public GeneratableCryptoMaterial
+{
+};
+
+//! interface for crypto prameters
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE CryptoParameters : public GeneratableCryptoMaterial
+{
+};
+
+//! interface for asymmetric algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AsymmetricAlgorithm : public Algorithm
+{
+public:
+       //! returns a reference to the crypto material used by this object
+       virtual CryptoMaterial & AccessMaterial() =0;
+       //! returns a const reference to the crypto material used by this object
+       virtual const CryptoMaterial & GetMaterial() const =0;
+
+       //! for backwards compatibility, calls AccessMaterial().Load(bt)
+       void BERDecode(BufferedTransformation &bt)
+               {AccessMaterial().Load(bt);}
+       //! for backwards compatibility, calls GetMaterial().Save(bt)
+       void DEREncode(BufferedTransformation &bt) const
+               {GetMaterial().Save(bt);}
+};
+
+//! interface for asymmetric algorithms using public keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PublicKeyAlgorithm : public AsymmetricAlgorithm
+{
+public:
+       // VC60 workaround: no co-variant return type
+       CryptoMaterial & AccessMaterial() {return AccessPublicKey();}
+       const CryptoMaterial & GetMaterial() const {return GetPublicKey();}
+
+       virtual PublicKey & AccessPublicKey() =0;
+       virtual const PublicKey & GetPublicKey() const {return const_cast<PublicKeyAlgorithm *>(this)->AccessPublicKey();}
+};
+
+//! interface for asymmetric algorithms using private keys
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PrivateKeyAlgorithm : public AsymmetricAlgorithm
+{
+public:
+       CryptoMaterial & AccessMaterial() {return AccessPrivateKey();}
+       const CryptoMaterial & GetMaterial() const {return GetPrivateKey();}
+
+       virtual PrivateKey & AccessPrivateKey() =0;
+       virtual const PrivateKey & GetPrivateKey() const {return const_cast<PrivateKeyAlgorithm *>(this)->AccessPrivateKey();}
+};
+
+//! interface for key agreement algorithms
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE KeyAgreementAlgorithm : public AsymmetricAlgorithm
+{
+public:
+       CryptoMaterial & AccessMaterial() {return AccessCryptoParameters();}
+       const CryptoMaterial & GetMaterial() const {return GetCryptoParameters();}
+
+       virtual CryptoParameters & AccessCryptoParameters() =0;
+       virtual const CryptoParameters & GetCryptoParameters() const {return const_cast<KeyAgreementAlgorithm *>(this)->AccessCryptoParameters();}
+};
+
+//! interface for public-key encryptors and decryptors
+
+/*! This class provides an interface common to encryptors and decryptors
+       for querying their plaintext and ciphertext lengths.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_CryptoSystem
+{
+public:
+       virtual ~PK_CryptoSystem() {}
+
+       //! maximum length of plaintext for a given ciphertext length
+       /*! \note This function returns 0 if ciphertextLength is not valid (too long or too short). */
+       virtual size_t MaxPlaintextLength(size_t ciphertextLength) const =0;
+
+       //! calculate length of ciphertext given length of plaintext
+       /*! \note This function returns 0 if plaintextLength is not valid (too long). */
+       virtual size_t CiphertextLength(size_t plaintextLength) const =0;
+
+       //! this object supports the use of the parameter with the given name
+       /*! some possible parameter names: EncodingParameters, KeyDerivationParameters */
+       virtual bool ParameterSupported(const char *name) const =0;
+
+       //! return fixed ciphertext length, if one exists, otherwise return 0
+       /*! \note "Fixed" here means length of ciphertext does not depend on length of plaintext.
+               It usually does depend on the key length. */
+       virtual size_t FixedCiphertextLength() const {return 0;}
+
+       //! return maximum plaintext length given the fixed ciphertext length, if one exists, otherwise return 0
+       virtual size_t FixedMaxPlaintextLength() const {return 0;}
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+       size_t MaxPlainTextLength(size_t cipherTextLength) const {return MaxPlaintextLength(cipherTextLength);}
+       size_t CipherTextLength(size_t plainTextLength) const {return CiphertextLength(plainTextLength);}
+#endif
+};
+
+//! interface for public-key encryptors
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Encryptor : public PK_CryptoSystem, public PublicKeyAlgorithm
+{
+public:
+       //! exception thrown when trying to encrypt plaintext of invalid length
+       class CRYPTOPP_DLL InvalidPlaintextLength : public Exception
+       {
+       public:
+               InvalidPlaintextLength() : Exception(OTHER_ERROR, "PK_Encryptor: invalid plaintext length") {}
+       };
+
+       //! encrypt a byte string
+       /*! \pre CiphertextLength(plaintextLength) != 0 (i.e., plaintext isn't too long)
+               \pre size of ciphertext == CiphertextLength(plaintextLength)
+       */
+       virtual void Encrypt(RandomNumberGenerator &rng, 
+               const byte *plaintext, size_t plaintextLength, 
+               byte *ciphertext, const NameValuePairs &parameters = g_nullNameValuePairs) const =0;
+
+       //! create a new encryption filter
+       /*! \note The caller is responsible for deleting the returned pointer.
+               \note Encoding parameters should be passed in the "EP" channel.
+       */
+       virtual BufferedTransformation * CreateEncryptionFilter(RandomNumberGenerator &rng, 
+               BufferedTransformation *attachment=NULL, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+};
+
+//! interface for public-key decryptors
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Decryptor : public PK_CryptoSystem, public PrivateKeyAlgorithm
+{
+public:
+       //! decrypt a byte string, and return the length of plaintext
+       /*! \pre size of plaintext == MaxPlaintextLength(ciphertextLength) bytes.
+               \return the actual length of the plaintext, indication that decryption failed.
+       */
+       virtual DecodingResult Decrypt(RandomNumberGenerator &rng, 
+               const byte *ciphertext, size_t ciphertextLength, 
+               byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const =0;
+
+       //! create a new decryption filter
+       /*! \note caller is responsible for deleting the returned pointer
+       */
+       virtual BufferedTransformation * CreateDecryptionFilter(RandomNumberGenerator &rng, 
+               BufferedTransformation *attachment=NULL, const NameValuePairs &parameters = g_nullNameValuePairs) const;
+
+       //! decrypt a fixed size ciphertext
+       DecodingResult FixedLengthDecrypt(RandomNumberGenerator &rng, const byte *ciphertext, byte *plaintext, const NameValuePairs &parameters = g_nullNameValuePairs) const
+               {return Decrypt(rng, ciphertext, FixedCiphertextLength(), plaintext, parameters);}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef PK_CryptoSystem PK_FixedLengthCryptoSystem;
+typedef PK_Encryptor PK_FixedLengthEncryptor;
+typedef PK_Decryptor PK_FixedLengthDecryptor;
+#endif
+
+//! interface for public-key signers and verifiers
+
+/*! This class provides an interface common to signers and verifiers
+       for querying scheme properties.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_SignatureScheme
+{
+public:
+       //! invalid key exception, may be thrown by any function in this class if the private or public key has a length that can't be used
+       class CRYPTOPP_DLL InvalidKeyLength : public Exception
+       {
+       public:
+               InvalidKeyLength(const std::string &message) : Exception(OTHER_ERROR, message) {}
+       };
+
+       //! key too short exception, may be thrown by any function in this class if the private or public key is too short to sign or verify anything
+       class CRYPTOPP_DLL KeyTooShort : public InvalidKeyLength
+       {
+       public:
+               KeyTooShort() : InvalidKeyLength("PK_Signer: key too short for this signature scheme") {}
+       };
+
+       virtual ~PK_SignatureScheme() {}
+
+       //! signature length if it only depends on the key, otherwise 0
+       virtual size_t SignatureLength() const =0;
+
+       //! maximum signature length produced for a given length of recoverable message part
+       virtual size_t MaxSignatureLength(size_t recoverablePartLength = 0) const {return SignatureLength();}
+
+       //! length of longest message that can be recovered, or 0 if this signature scheme does not support message recovery
+       virtual size_t MaxRecoverableLength() const =0;
+
+       //! length of longest message that can be recovered from a signature of given length, or 0 if this signature scheme does not support message recovery
+       virtual size_t MaxRecoverableLengthFromSignatureLength(size_t signatureLength) const =0;
+
+       //! requires a random number generator to sign
+       /*! if this returns false, NullRNG() can be passed to functions that take RandomNumberGenerator & */
+       virtual bool IsProbabilistic() const =0;
+
+       //! whether or not a non-recoverable message part can be signed
+       virtual bool AllowNonrecoverablePart() const =0;
+
+       //! if this function returns true, during verification you must input the signature before the message, otherwise you can input it at anytime */
+       virtual bool SignatureUpfront() const {return false;}
+
+       //! whether you must input the recoverable part before the non-recoverable part during signing
+       virtual bool RecoverablePartFirst() const =0;
+};
+
+//! interface for accumulating messages to be signed or verified
+/*! Only Update() should be called
+       on this class. No other functions inherited from HashTransformation should be called.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_MessageAccumulator : public HashTransformation
+{
+public:
+       //! should not be called on PK_MessageAccumulator
+       unsigned int DigestSize() const
+               {throw NotImplemented("PK_MessageAccumulator: DigestSize() should not be called");}
+       //! should not be called on PK_MessageAccumulator
+       void TruncatedFinal(byte *digest, size_t digestSize) 
+               {throw NotImplemented("PK_MessageAccumulator: TruncatedFinal() should not be called");}
+};
+
+//! interface for public-key signers
+
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Signer : public PK_SignatureScheme, public PrivateKeyAlgorithm
+{
+public:
+       //! create a new HashTransformation to accumulate the message to be signed
+       virtual PK_MessageAccumulator * NewSignatureAccumulator(RandomNumberGenerator &rng) const =0;
+
+       virtual void InputRecoverableMessage(PK_MessageAccumulator &messageAccumulator, const byte *recoverableMessage, size_t recoverableMessageLength) const =0;
+
+       //! sign and delete messageAccumulator (even in case of exception thrown)
+       /*! \pre size of signature == MaxSignatureLength()
+               \return actual signature length
+       */
+       virtual size_t Sign(RandomNumberGenerator &rng, PK_MessageAccumulator *messageAccumulator, byte *signature) const;
+
+       //! sign and restart messageAccumulator
+       /*! \pre size of signature == MaxSignatureLength()
+               \return actual signature length
+       */
+       virtual size_t SignAndRestart(RandomNumberGenerator &rng, PK_MessageAccumulator &messageAccumulator, byte *signature, bool restart=true) const =0;
+
+       //! sign a message
+       /*! \pre size of signature == MaxSignatureLength()
+               \return actual signature length
+       */
+       virtual size_t SignMessage(RandomNumberGenerator &rng, const byte *message, size_t messageLen, byte *signature) const;
+
+       //! sign a recoverable message
+       /*! \pre size of signature == MaxSignatureLength(recoverableMessageLength)
+               \return actual signature length
+       */
+       virtual size_t SignMessageWithRecovery(RandomNumberGenerator &rng, const byte *recoverableMessage, size_t recoverableMessageLength, 
+               const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, byte *signature) const;
+};
+
+//! interface for public-key signature verifiers
+/*! The Recover* functions throw NotImplemented if the signature scheme does not support
+       message recovery.
+       The Verify* functions throw InvalidDataFormat if the scheme does support message
+       recovery and the signature contains a non-empty recoverable message part. The
+       Recovery* functions should be used in that case.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE PK_Verifier : public PK_SignatureScheme, public PublicKeyAlgorithm
+{
+public:
+       //! create a new HashTransformation to accumulate the message to be verified
+       virtual PK_MessageAccumulator * NewVerificationAccumulator() const =0;
+
+       //! input signature into a message accumulator
+       virtual void InputSignature(PK_MessageAccumulator &messageAccumulator, const byte *signature, size_t signatureLength) const =0;
+
+       //! check whether messageAccumulator contains a valid signature and message, and delete messageAccumulator (even in case of exception thrown)
+       virtual bool Verify(PK_MessageAccumulator *messageAccumulator) const;
+
+       //! check whether messageAccumulator contains a valid signature and message, and restart messageAccumulator
+       virtual bool VerifyAndRestart(PK_MessageAccumulator &messageAccumulator) const =0;
+
+       //! check whether input signature is a valid signature for input message
+       virtual bool VerifyMessage(const byte *message, size_t messageLen, 
+               const byte *signature, size_t signatureLength) const;
+
+       //! recover a message from its signature
+       /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+       */
+       virtual DecodingResult Recover(byte *recoveredMessage, PK_MessageAccumulator *messageAccumulator) const;
+
+       //! recover a message from its signature
+       /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+       */
+       virtual DecodingResult RecoverAndRestart(byte *recoveredMessage, PK_MessageAccumulator &messageAccumulator) const =0;
+
+       //! recover a message from its signature
+       /*! \pre size of recoveredMessage == MaxRecoverableLengthFromSignatureLength(signatureLength)
+       */
+       virtual DecodingResult RecoverMessage(byte *recoveredMessage, 
+               const byte *nonrecoverableMessage, size_t nonrecoverableMessageLength, 
+               const byte *signature, size_t signatureLength) const;
+};
+
+//! interface for domains of simple key agreement protocols
+
+/*! A key agreement domain is a set of parameters that must be shared
+       by two parties in a key agreement protocol, along with the algorithms
+       for generating key pairs and deriving agreed values.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE SimpleKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+       //! return length of agreed value produced
+       virtual unsigned int AgreedValueLength() const =0;
+       //! return length of private keys in this domain
+       virtual unsigned int PrivateKeyLength() const =0;
+       //! return length of public keys in this domain
+       virtual unsigned int PublicKeyLength() const =0;
+       //! generate private key
+       /*! \pre size of privateKey == PrivateKeyLength() */
+       virtual void GeneratePrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+       //! generate public key
+       /*!     \pre size of publicKey == PublicKeyLength() */
+       virtual void GeneratePublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+       //! generate private/public key pair
+       /*! \note equivalent to calling GeneratePrivateKey() and then GeneratePublicKey() */
+       virtual void GenerateKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+       //! derive agreed value from your private key and couterparty's public key, return false in case of failure
+       /*! \note If you have previously validated the public key, use validateOtherPublicKey=false to save time.
+               \pre size of agreedValue == AgreedValueLength()
+               \pre length of privateKey == PrivateKeyLength()
+               \pre length of otherPublicKey == PublicKeyLength()
+       */
+       virtual bool Agree(byte *agreedValue, const byte *privateKey, const byte *otherPublicKey, bool validateOtherPublicKey=true) const =0;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+       bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+               {return GetCryptoParameters().Validate(rng, 2);}
+#endif
+};
+
+//! interface for domains of authenticated key agreement protocols
+
+/*! In an authenticated key agreement protocol, each party has two
+       key pairs. The long-lived key pair is called the static key pair,
+       and the short-lived key pair is called the ephemeral key pair.
+*/
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE AuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+       //! return length of agreed value produced
+       virtual unsigned int AgreedValueLength() const =0;
+
+       //! return length of static private keys in this domain
+       virtual unsigned int StaticPrivateKeyLength() const =0;
+       //! return length of static public keys in this domain
+       virtual unsigned int StaticPublicKeyLength() const =0;
+       //! generate static private key
+       /*! \pre size of privateKey == PrivateStaticKeyLength() */
+       virtual void GenerateStaticPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+       //! generate static public key
+       /*!     \pre size of publicKey == PublicStaticKeyLength() */
+       virtual void GenerateStaticPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+       //! generate private/public key pair
+       /*! \note equivalent to calling GenerateStaticPrivateKey() and then GenerateStaticPublicKey() */
+       virtual void GenerateStaticKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+
+       //! return length of ephemeral private keys in this domain
+       virtual unsigned int EphemeralPrivateKeyLength() const =0;
+       //! return length of ephemeral public keys in this domain
+       virtual unsigned int EphemeralPublicKeyLength() const =0;
+       //! generate ephemeral private key
+       /*! \pre size of privateKey == PrivateEphemeralKeyLength() */
+       virtual void GenerateEphemeralPrivateKey(RandomNumberGenerator &rng, byte *privateKey) const =0;
+       //! generate ephemeral public key
+       /*!     \pre size of publicKey == PublicEphemeralKeyLength() */
+       virtual void GenerateEphemeralPublicKey(RandomNumberGenerator &rng, const byte *privateKey, byte *publicKey) const =0;
+       //! generate private/public key pair
+       /*! \note equivalent to calling GenerateEphemeralPrivateKey() and then GenerateEphemeralPublicKey() */
+       virtual void GenerateEphemeralKeyPair(RandomNumberGenerator &rng, byte *privateKey, byte *publicKey) const;
+
+       //! derive agreed value from your private keys and couterparty's public keys, return false in case of failure
+       /*! \note The ephemeral public key will always be validated.
+                     If you have previously validated the static public key, use validateStaticOtherPublicKey=false to save time.
+               \pre size of agreedValue == AgreedValueLength()
+               \pre length of staticPrivateKey == StaticPrivateKeyLength()
+               \pre length of ephemeralPrivateKey == EphemeralPrivateKeyLength()
+               \pre length of staticOtherPublicKey == StaticPublicKeyLength()
+               \pre length of ephemeralOtherPublicKey == EphemeralPublicKeyLength()
+       */
+       virtual bool Agree(byte *agreedValue,
+               const byte *staticPrivateKey, const byte *ephemeralPrivateKey,
+               const byte *staticOtherPublicKey, const byte *ephemeralOtherPublicKey,
+               bool validateStaticOtherPublicKey=true) const =0;
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+       bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+               {return GetCryptoParameters().Validate(rng, 2);}
+#endif
+};
+
+// interface for password authenticated key agreement protocols, not implemented yet
+#if 0
+//! interface for protocol sessions
+/*! The methods should be called in the following order:
+
+       InitializeSession(rng, parameters);     // or call initialize method in derived class
+       while (true)
+       {
+               if (OutgoingMessageAvailable())
+               {
+                       length = GetOutgoingMessageLength();
+                       GetOutgoingMessage(message);
+                       ; // send outgoing message
+               }
+
+               if (LastMessageProcessed())
+                       break;
+
+               ; // receive incoming message
+               ProcessIncomingMessage(message);
+       }
+       ; // call methods in derived class to obtain result of protocol session
+*/
+class ProtocolSession
+{
+public:
+       //! exception thrown when an invalid protocol message is processed
+       class ProtocolError : public Exception
+       {
+       public:
+               ProtocolError(ErrorType errorType, const std::string &s) : Exception(errorType, s) {}
+       };
+
+       //! exception thrown when a function is called unexpectedly
+       /*! for example calling ProcessIncomingMessage() when ProcessedLastMessage() == true */
+       class UnexpectedMethodCall : public Exception
+       {
+       public:
+               UnexpectedMethodCall(const std::string &s) : Exception(OTHER_ERROR, s) {}
+       };
+
+       ProtocolSession() : m_rng(NULL), m_throwOnProtocolError(true), m_validState(false) {}
+       virtual ~ProtocolSession() {}
+
+       virtual void InitializeSession(RandomNumberGenerator &rng, const NameValuePairs &parameters) =0;
+
+       bool GetThrowOnProtocolError() const {return m_throwOnProtocolError;}
+       void SetThrowOnProtocolError(bool throwOnProtocolError) {m_throwOnProtocolError = throwOnProtocolError;}
+
+       bool HasValidState() const {return m_validState;}
+
+       virtual bool OutgoingMessageAvailable() const =0;
+       virtual unsigned int GetOutgoingMessageLength() const =0;
+       virtual void GetOutgoingMessage(byte *message) =0;
+
+       virtual bool LastMessageProcessed() const =0;
+       virtual void ProcessIncomingMessage(const byte *message, unsigned int messageLength) =0;
+
+protected:
+       void HandleProtocolError(Exception::ErrorType errorType, const std::string &s) const;
+       void CheckAndHandleInvalidState() const;
+       void SetValidState(bool valid) {m_validState = valid;}
+
+       RandomNumberGenerator *m_rng;
+
+private:
+       bool m_throwOnProtocolError, m_validState;
+};
+
+class KeyAgreementSession : public ProtocolSession
+{
+public:
+       virtual unsigned int GetAgreedValueLength() const =0;
+       virtual void GetAgreedValue(byte *agreedValue) const =0;
+};
+
+class PasswordAuthenticatedKeyAgreementSession : public KeyAgreementSession
+{
+public:
+       void InitializePasswordAuthenticatedKeyAgreementSession(RandomNumberGenerator &rng, 
+               const byte *myId, unsigned int myIdLength, 
+               const byte *counterPartyId, unsigned int counterPartyIdLength, 
+               const byte *passwordOrVerifier, unsigned int passwordOrVerifierLength);
+};
+
+class PasswordAuthenticatedKeyAgreementDomain : public KeyAgreementAlgorithm
+{
+public:
+       //! return whether the domain parameters stored in this object are valid
+       virtual bool ValidateDomainParameters(RandomNumberGenerator &rng) const
+               {return GetCryptoParameters().Validate(rng, 2);}
+
+       virtual unsigned int GetPasswordVerifierLength(const byte *password, unsigned int passwordLength) const =0;
+       virtual void GeneratePasswordVerifier(RandomNumberGenerator &rng, const byte *userId, unsigned int userIdLength, const byte *password, unsigned int passwordLength, byte *verifier) const =0;
+
+       enum RoleFlags {CLIENT=1, SERVER=2, INITIATOR=4, RESPONDER=8};
+
+       virtual bool IsValidRole(unsigned int role) =0;
+       virtual PasswordAuthenticatedKeyAgreementSession * CreateProtocolSession(unsigned int role) const =0;
+};
+#endif
+
+//! BER Decode Exception Class, may be thrown during an ASN1 BER decode operation
+class CRYPTOPP_DLL BERDecodeErr : public InvalidArgument
+{
+public: 
+       BERDecodeErr() : InvalidArgument("BER decode error") {}
+       BERDecodeErr(const std::string &s) : InvalidArgument(s) {}
+};
+
+//! interface for encoding and decoding ASN1 objects
+class CRYPTOPP_DLL CRYPTOPP_NO_VTABLE ASN1Object
+{
+public:
+       virtual ~ASN1Object() {}
+       //! decode this object from a BufferedTransformation, using BER (Basic Encoding Rules)
+       virtual void BERDecode(BufferedTransformation &bt) =0;
+       //! encode this object into a BufferedTransformation, using DER (Distinguished Encoding Rules)
+       virtual void DEREncode(BufferedTransformation &bt) const =0;
+       //! encode this object into a BufferedTransformation, using BER
+       /*! this may be useful if DEREncode() would be too inefficient */
+       virtual void BEREncode(BufferedTransformation &bt) const {DEREncode(bt);}
+};
+
+#ifdef CRYPTOPP_MAINTAIN_BACKWARDS_COMPATIBILITY
+typedef PK_SignatureScheme PK_SignatureSystem;
+typedef SimpleKeyAgreementDomain PK_SimpleKeyAgreementDomain;
+typedef AuthenticatedKeyAgreementDomain PK_AuthenticatedKeyAgreementDomain;
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/iterhash.h b/cryptopp/include/cryptopp/iterhash.h
new file mode 100644 (file)
index 0000000..0e2a147
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef CRYPTOPP_ITERHASH_H
+#define CRYPTOPP_ITERHASH_H
+
+#include "cryptopp/secblock.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// *** trimmed down dependency from iterhash.h ***
+template <class T_HashWordType, class T_Endianness, unsigned int T_BlockSize, unsigned int T_StateSize, class T_Transform, unsigned int T_DigestSize = 0, bool T_StateAligned = false>
+class CRYPTOPP_NO_VTABLE IteratedHashWithStaticTransform
+{
+public:
+       CRYPTOPP_CONSTANT(DIGESTSIZE = T_DigestSize ? T_DigestSize : T_StateSize)
+       unsigned int DigestSize() const {return DIGESTSIZE;};
+    typedef T_HashWordType HashWordType;
+    CRYPTOPP_CONSTANT(BLOCKSIZE = T_BlockSize)
+
+protected:
+       IteratedHashWithStaticTransform() {this->Init();}
+       void HashEndianCorrectedBlock(const T_HashWordType *data) {T_Transform::Transform(this->m_state, data);}
+       void Init() {T_Transform::InitState(this->m_state);}
+
+       T_HashWordType* StateBuf() {return this->m_state;}
+       FixedSizeAlignedSecBlock<T_HashWordType, T_BlockSize/sizeof(T_HashWordType), T_StateAligned> m_state;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/misc.h b/cryptopp/include/cryptopp/misc.h
new file mode 100644 (file)
index 0000000..5258e2a
--- /dev/null
@@ -0,0 +1,1134 @@
+#ifndef CRYPTOPP_MISC_H
+#define CRYPTOPP_MISC_H
+
+#include "cryptopp/cryptlib.h"
+#include "cryptopp/smartptr.h"
+#include <string.h>            // for memcpy and memmove
+
+#ifdef _MSC_VER
+       #include <stdlib.h>
+       #if _MSC_VER >= 1400
+               // VC2005 workaround: disable declarations that conflict with winnt.h
+               #define _interlockedbittestandset CRYPTOPP_DISABLED_INTRINSIC_1
+               #define _interlockedbittestandreset CRYPTOPP_DISABLED_INTRINSIC_2
+               #define _interlockedbittestandset64 CRYPTOPP_DISABLED_INTRINSIC_3
+               #define _interlockedbittestandreset64 CRYPTOPP_DISABLED_INTRINSIC_4
+               #include <intrin.h>
+               #undef _interlockedbittestandset
+               #undef _interlockedbittestandreset
+               #undef _interlockedbittestandset64
+               #undef _interlockedbittestandreset64
+               #define CRYPTOPP_FAST_ROTATE(x) 1
+       #elif _MSC_VER >= 1300
+               #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32 | (x) == 64)
+       #else
+               #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
+       #endif
+#elif (defined(__MWERKS__) && TARGET_CPU_PPC) || \
+       (defined(__GNUC__) && (defined(_ARCH_PWR2) || defined(_ARCH_PWR) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(_ARCH_COM)))
+       #define CRYPTOPP_FAST_ROTATE(x) ((x) == 32)
+#elif defined(__GNUC__) && (CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X86)    // depend on GCC's peephole optimization to generate rotate instructions
+       #define CRYPTOPP_FAST_ROTATE(x) 1
+#else
+       #define CRYPTOPP_FAST_ROTATE(x) 0
+#endif
+
+#ifdef __BORLANDC__
+#include <mem.h>
+#endif
+
+#if defined(__GNUC__) && defined(__linux__)
+#define CRYPTOPP_BYTESWAP_AVAILABLE
+#include <byteswap.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** compile-time assertion ***************
+
+template <bool b>
+struct CompileAssert
+{
+       static char dummy[2*b-1];
+};
+
+#define CRYPTOPP_COMPILE_ASSERT(assertion) CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, __LINE__)
+#if defined(CRYPTOPP_EXPORTS) || defined(CRYPTOPP_IMPORTS)
+#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance)
+#else
+#define CRYPTOPP_COMPILE_ASSERT_INSTANCE(assertion, instance) static CompileAssert<(assertion)> CRYPTOPP_ASSERT_JOIN(cryptopp_assert_, instance)
+#endif
+#define CRYPTOPP_ASSERT_JOIN(X, Y) CRYPTOPP_DO_ASSERT_JOIN(X, Y)
+#define CRYPTOPP_DO_ASSERT_JOIN(X, Y) X##Y
+
+// ************** misc classes ***************
+
+class CRYPTOPP_DLL Empty
+{
+};
+
+//! _
+template <class BASE1, class BASE2>
+class CRYPTOPP_NO_VTABLE TwoBases : public BASE1, public BASE2
+{
+};
+
+//! _
+template <class BASE1, class BASE2, class BASE3>
+class CRYPTOPP_NO_VTABLE ThreeBases : public BASE1, public BASE2, public BASE3
+{
+};
+
+template <class T>
+class ObjectHolder
+{
+protected:
+       T m_object;
+};
+
+class NotCopyable
+{
+public:
+       NotCopyable() {}
+private:
+    NotCopyable(const NotCopyable &);
+    void operator=(const NotCopyable &);
+};
+
+template <class T>
+struct NewObject
+{
+       T* operator()() const {return new T;}
+};
+
+/*! This function safely initializes a static object in a multithreaded environment without using locks.
+       It may leak memory when two threads try to initialize the static object at the same time
+       but this should be acceptable since each static object is only initialized once per session.
+*/
+template <class T, class F = NewObject<T>, int instance=0>
+class Singleton
+{
+public:
+       Singleton(F objectFactory = F()) : m_objectFactory(objectFactory) {}
+
+       // prevent this function from being inlined
+       CRYPTOPP_NOINLINE const T & Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const;
+
+private:
+       F m_objectFactory;
+};
+
+template <class T, class F, int instance>
+const T & Singleton<T, F, instance>::Ref(CRYPTOPP_NOINLINE_DOTDOTDOT) const
+{
+       static simple_ptr<T> s_pObject;
+       static char s_objectState = 0;
+
+retry:
+       switch (s_objectState)
+       {
+       case 0:
+               s_objectState = 1;
+               try
+               {
+                       s_pObject.m_p = m_objectFactory();
+               }
+               catch(...)
+               {
+                       s_objectState = 0;
+                       throw;
+               }
+               s_objectState = 2;
+               break;
+       case 1:
+               goto retry;
+       default:
+               break;
+       }
+       return *s_pObject.m_p;
+}
+
+// ************** misc functions ***************
+
+#if (!__STDC_WANT_SECURE_LIB__)
+inline void memcpy_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
+{
+       if (count > sizeInBytes)
+               throw InvalidArgument("memcpy_s: buffer overflow");
+       memcpy(dest, src, count);
+}
+
+inline void memmove_s(void *dest, size_t sizeInBytes, const void *src, size_t count)
+{
+       if (count > sizeInBytes)
+               throw InvalidArgument("memmove_s: buffer overflow");
+       memmove(dest, src, count);
+}
+#endif
+
+inline void * memset_z(void *ptr, int value, size_t num)
+{
+// avoid extranous warning on GCC 4.3.2 Ubuntu 8.10
+#if CRYPTOPP_GCC_VERSION >= 30001
+       if (__builtin_constant_p(num) && num==0)
+               return ptr;
+#endif
+       return memset(ptr, value, num);
+}
+
+// can't use std::min or std::max in MSVC60 or Cygwin 1.1.0
+template <class T> inline const T& STDMIN(const T& a, const T& b)
+{
+       return b < a ? b : a;
+}
+
+template <class T1, class T2> inline const T1 UnsignedMin(const T1& a, const T2& b)
+{
+       CRYPTOPP_COMPILE_ASSERT((sizeof(T1)<=sizeof(T2) && T2(-1)>0) || (sizeof(T1)>sizeof(T2) && T1(-1)>0));
+       assert(a==0 || a>0);    // GCC workaround: get rid of the warning "comparison is always true due to limited range of data type"
+       assert(b>=0);
+
+       if (sizeof(T1)<=sizeof(T2))
+               return b < (T2)a ? (T1)b : a;
+       else
+               return (T1)b < a ? (T1)b : a;
+}
+
+template <class T> inline const T& STDMAX(const T& a, const T& b)
+{
+       return a < b ? b : a;
+}
+
+#define RETURN_IF_NONZERO(x) size_t returnedValue = x; if (returnedValue) return returnedValue
+
+// this version of the macro is fastest on Pentium 3 and Pentium 4 with MSVC 6 SP5 w/ Processor Pack
+#define GETBYTE(x, y) (unsigned int)byte((x)>>(8*(y)))
+// these may be faster on other CPUs/compilers
+// #define GETBYTE(x, y) (unsigned int)(((x)>>(8*(y)))&255)
+// #define GETBYTE(x, y) (((byte *)&(x))[y])
+
+#define CRYPTOPP_GET_BYTE_AS_BYTE(x, y) byte((x)>>(8*(y)))
+
+template <class T>
+unsigned int Parity(T value)
+{
+       for (unsigned int i=8*sizeof(value)/2; i>0; i/=2)
+               value ^= value >> i;
+       return (unsigned int)value&1;
+}
+
+template <class T>
+unsigned int BytePrecision(const T &value)
+{
+       if (!value)
+               return 0;
+
+       unsigned int l=0, h=8*sizeof(value);
+
+       while (h-l > 8)
+       {
+               unsigned int t = (l+h)/2;
+               if (value >> t)
+                       l = t;
+               else
+                       h = t;
+       }
+
+       return h/8;
+}
+
+template <class T>
+unsigned int BitPrecision(const T &value)
+{
+       if (!value)
+               return 0;
+
+       unsigned int l=0, h=8*sizeof(value);
+
+       while (h-l > 1)
+       {
+               unsigned int t = (l+h)/2;
+               if (value >> t)
+                       l = t;
+               else
+                       h = t;
+       }
+
+       return h;
+}
+
+template <class T>
+inline T Crop(T value, size_t size)
+{
+       if (size < 8*sizeof(value))
+       return T(value & ((T(1) << size) - 1));
+       else
+               return value;
+}
+
+template <class T1, class T2>
+inline bool SafeConvert(T1 from, T2 &to)
+{
+       to = (T2)from;
+       if (from != to || (from > 0) != (to > 0))
+               return false;
+       return true;
+}
+
+inline size_t BitsToBytes(size_t bitCount)
+{
+       return ((bitCount+7)/(8));
+}
+
+inline size_t BytesToWords(size_t byteCount)
+{
+       return ((byteCount+WORD_SIZE-1)/WORD_SIZE);
+}
+
+inline size_t BitsToWords(size_t bitCount)
+{
+       return ((bitCount+WORD_BITS-1)/(WORD_BITS));
+}
+
+inline size_t BitsToDwords(size_t bitCount)
+{
+       return ((bitCount+2*WORD_BITS-1)/(2*WORD_BITS));
+}
+
+CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *buf, const byte *mask, size_t count);
+CRYPTOPP_DLL void CRYPTOPP_API xorbuf(byte *output, const byte *input, const byte *mask, size_t count);
+
+CRYPTOPP_DLL bool CRYPTOPP_API VerifyBufsEqual(const byte *buf1, const byte *buf2, size_t count);
+
+template <class T>
+inline bool IsPowerOf2(const T &n)
+{
+       return n > 0 && (n & (n-1)) == 0;
+}
+
+template <class T1, class T2>
+inline T2 ModPowerOf2(const T1 &a, const T2 &b)
+{
+       assert(IsPowerOf2(b));
+       return T2(a) & (b-1);
+}
+
+template <class T1, class T2>
+inline T1 RoundDownToMultipleOf(const T1 &n, const T2 &m)
+{
+       if (IsPowerOf2(m))
+               return n - ModPowerOf2(n, m);
+       else
+               return n - n%m;
+}
+
+template <class T1, class T2>
+inline T1 RoundUpToMultipleOf(const T1 &n, const T2 &m)
+{
+       if (n+m-1 < n)
+               throw InvalidArgument("RoundUpToMultipleOf: integer overflow");
+       return RoundDownToMultipleOf(n+m-1, m);
+}
+
+template <class T>
+inline unsigned int GetAlignmentOf(T *dummy=NULL)      // VC60 workaround
+{
+#ifdef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+       if (sizeof(T) < 16)
+               return 1;
+#endif
+
+#if (_MSC_VER >= 1300)
+       return __alignof(T);
+#elif defined(__GNUC__)
+       return __alignof__(T);
+#elif CRYPTOPP_BOOL_SLOW_WORD64
+       return UnsignedMin(4U, sizeof(T));
+#else
+       return sizeof(T);
+#endif
+}
+
+inline bool IsAlignedOn(const void *p, unsigned int alignment)
+{
+       return alignment==1 || (IsPowerOf2(alignment) ? ModPowerOf2((size_t)p, alignment) == 0 : (size_t)p % alignment == 0);
+}
+
+template <class T>
+inline bool IsAligned(const void *p, T *dummy=NULL)    // VC60 workaround
+{
+       return IsAlignedOn(p, GetAlignmentOf<T>());
+}
+
+#ifdef IS_LITTLE_ENDIAN
+       typedef LittleEndian NativeByteOrder;
+#else
+       typedef BigEndian NativeByteOrder;
+#endif
+
+inline ByteOrder GetNativeByteOrder()
+{
+       return NativeByteOrder::ToEnum();
+}
+
+inline bool NativeByteOrderIs(ByteOrder order)
+{
+       return order == GetNativeByteOrder();
+}
+
+template <class T>
+std::string IntToString(T a, unsigned int base = 10)
+{
+       if (a == 0)
+               return "0";
+       bool negate = false;
+       if (a < 0)
+       {
+               negate = true;
+               a = 0-a;        // VC .NET does not like -a
+       }
+       std::string result;
+       while (a > 0)
+       {
+               T digit = a % base;
+               result = char((digit < 10 ? '0' : ('a' - 10)) + digit) + result;
+               a /= base;
+       }
+       if (negate)
+               result = "-" + result;
+       return result;
+}
+
+template <class T1, class T2>
+inline T1 SaturatingSubtract(const T1 &a, const T2 &b)
+{
+       return T1((a > b) ? (a - b) : 0);
+}
+
+template <class T>
+inline CipherDir GetCipherDir(const T &obj)
+{
+       return obj.IsForwardTransformation() ? ENCRYPTION : DECRYPTION;
+}
+
+CRYPTOPP_DLL void CRYPTOPP_API CallNewHandler();
+
+inline void IncrementCounterByOne(byte *inout, unsigned int s)
+{
+       for (int i=s-1, carry=1; i>=0 && carry; i--)
+               carry = !++inout[i];
+}
+
+inline void IncrementCounterByOne(byte *output, const byte *input, unsigned int s)
+{
+       int i, carry;
+       for (i=s-1, carry=1; i>=0 && carry; i--)
+               carry = ((output[i] = input[i]+1) == 0);
+       memcpy_s(output, s, input, i+1);
+}
+
+// ************** rotate functions ***************
+
+template <class T> inline T rotlFixed(T x, unsigned int y)
+{
+       assert(y < sizeof(T)*8);
+       return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrFixed(T x, unsigned int y)
+{
+       assert(y < sizeof(T)*8);
+       return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotlVariable(T x, unsigned int y)
+{
+       assert(y < sizeof(T)*8);
+       return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrVariable(T x, unsigned int y)
+{
+       assert(y < sizeof(T)*8);
+       return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotlMod(T x, unsigned int y)
+{
+       y %= sizeof(T)*8;
+       return T((x<<y) | (x>>(sizeof(T)*8-y)));
+}
+
+template <class T> inline T rotrMod(T x, unsigned int y)
+{
+       y %= sizeof(T)*8;
+       return T((x>>y) | (x<<(sizeof(T)*8-y)));
+}
+
+#ifdef _MSC_VER
+
+template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _lrotl(x, y) : x;
+}
+
+template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _lrotr(x, y) : x;
+}
+
+template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _lrotl(x, y);
+}
+
+template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _lrotr(x, y);
+}
+
+template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
+{
+       return _lrotl(x, y);
+}
+
+template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
+{
+       return _lrotr(x, y);
+}
+
+#endif // #ifdef _MSC_VER
+
+#if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER)
+// Intel C++ Compiler 10.0 calls a function instead of using the rotate instruction when using these instructions
+
+template<> inline word64 rotlFixed<word64>(word64 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _rotl64(x, y) : x;
+}
+
+template<> inline word64 rotrFixed<word64>(word64 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _rotr64(x, y) : x;
+}
+
+template<> inline word64 rotlVariable<word64>(word64 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _rotl64(x, y);
+}
+
+template<> inline word64 rotrVariable<word64>(word64 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _rotr64(x, y);
+}
+
+template<> inline word64 rotlMod<word64>(word64 x, unsigned int y)
+{
+       return _rotl64(x, y);
+}
+
+template<> inline word64 rotrMod<word64>(word64 x, unsigned int y)
+{
+       return _rotr64(x, y);
+}
+
+#endif // #if _MSC_VER >= 1310
+
+#if _MSC_VER >= 1400 && !defined(__INTEL_COMPILER)
+// Intel C++ Compiler 10.0 gives undefined externals with these
+
+template<> inline word16 rotlFixed<word16>(word16 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _rotl16(x, y) : x;
+}
+
+template<> inline word16 rotrFixed<word16>(word16 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _rotr16(x, y) : x;
+}
+
+template<> inline word16 rotlVariable<word16>(word16 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _rotl16(x, y);
+}
+
+template<> inline word16 rotrVariable<word16>(word16 x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _rotr16(x, y);
+}
+
+template<> inline word16 rotlMod<word16>(word16 x, unsigned int y)
+{
+       return _rotl16(x, y);
+}
+
+template<> inline word16 rotrMod<word16>(word16 x, unsigned int y)
+{
+       return _rotr16(x, y);
+}
+
+template<> inline byte rotlFixed<byte>(byte x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _rotl8(x, y) : x;
+}
+
+template<> inline byte rotrFixed<byte>(byte x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return y ? _rotr8(x, y) : x;
+}
+
+template<> inline byte rotlVariable<byte>(byte x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _rotl8(x, y);
+}
+
+template<> inline byte rotrVariable<byte>(byte x, unsigned int y)
+{
+       assert(y < 8*sizeof(x));
+       return _rotr8(x, y);
+}
+
+template<> inline byte rotlMod<byte>(byte x, unsigned int y)
+{
+       return _rotl8(x, y);
+}
+
+template<> inline byte rotrMod<byte>(byte x, unsigned int y)
+{
+       return _rotr8(x, y);
+}
+
+#endif // #if _MSC_VER >= 1400
+
+#if (defined(__MWERKS__) && TARGET_CPU_PPC)
+
+template<> inline word32 rotlFixed<word32>(word32 x, unsigned int y)
+{
+       assert(y < 32);
+       return y ? __rlwinm(x,y,0,31) : x;
+}
+
+template<> inline word32 rotrFixed<word32>(word32 x, unsigned int y)
+{
+       assert(y < 32);
+       return y ? __rlwinm(x,32-y,0,31) : x;
+}
+
+template<> inline word32 rotlVariable<word32>(word32 x, unsigned int y)
+{
+       assert(y < 32);
+       return (__rlwnm(x,y,0,31));
+}
+
+template<> inline word32 rotrVariable<word32>(word32 x, unsigned int y)
+{
+       assert(y < 32);
+       return (__rlwnm(x,32-y,0,31));
+}
+
+template<> inline word32 rotlMod<word32>(word32 x, unsigned int y)
+{
+       return (__rlwnm(x,y,0,31));
+}
+
+template<> inline word32 rotrMod<word32>(word32 x, unsigned int y)
+{
+       return (__rlwnm(x,32-y,0,31));
+}
+
+#endif // #if (defined(__MWERKS__) && TARGET_CPU_PPC)
+
+// ************** endian reversal ***************
+
+template <class T>
+inline unsigned int GetByte(ByteOrder order, T value, unsigned int index)
+{
+       if (order == LITTLE_ENDIAN_ORDER)
+               return GETBYTE(value, index);
+       else
+               return GETBYTE(value, sizeof(T)-index-1);
+}
+
+inline byte ByteReverse(byte value)
+{
+       return value;
+}
+
+inline word16 ByteReverse(word16 value)
+{
+#ifdef CRYPTOPP_BYTESWAP_AVAILABLE
+       return bswap_16(value);
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+       return _byteswap_ushort(value);
+#else
+       return rotlFixed(value, 8U);
+#endif
+}
+
+inline word32 ByteReverse(word32 value)
+{
+#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE)
+       __asm__ ("bswap %0" : "=r" (value) : "0" (value));
+       return value;
+#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
+       return bswap_32(value);
+#elif defined(__MWERKS__) && TARGET_CPU_PPC
+       return (word32)__lwbrx(&value,0);
+#elif _MSC_VER >= 1400 || (_MSC_VER >= 1300 && !defined(_DLL))
+       return _byteswap_ulong(value);
+#elif CRYPTOPP_FAST_ROTATE(32)
+       // 5 instructions with rotate instruction, 9 without
+       return (rotrFixed(value, 8U) & 0xff00ff00) | (rotlFixed(value, 8U) & 0x00ff00ff);
+#else
+       // 6 instructions with rotate instruction, 8 without
+       value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8);
+       return rotlFixed(value, 16U);
+#endif
+}
+
+inline word64 ByteReverse(word64 value)
+{
+#if defined(__GNUC__) && defined(CRYPTOPP_X86_ASM_AVAILABLE) && defined(__x86_64__)
+       __asm__ ("bswap %0" : "=r" (value) : "0" (value));
+       return value;
+#elif defined(CRYPTOPP_BYTESWAP_AVAILABLE)
+       return bswap_64(value);
+#elif defined(_MSC_VER) && _MSC_VER >= 1300
+       return _byteswap_uint64(value);
+#elif CRYPTOPP_BOOL_SLOW_WORD64
+       return (word64(ByteReverse(word32(value))) << 32) | ByteReverse(word32(value>>32));
+#else
+       value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | ((value & W64LIT(0x00FF00FF00FF00FF)) << 8);
+       value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | ((value & W64LIT(0x0000FFFF0000FFFF)) << 16);
+       return rotlFixed(value, 32U);
+#endif
+}
+
+inline byte BitReverse(byte value)
+{
+       value = ((value & 0xAA) >> 1) | ((value & 0x55) << 1);
+       value = ((value & 0xCC) >> 2) | ((value & 0x33) << 2);
+       return rotlFixed(value, 4U);
+}
+
+inline word16 BitReverse(word16 value)
+{
+       value = ((value & 0xAAAA) >> 1) | ((value & 0x5555) << 1);
+       value = ((value & 0xCCCC) >> 2) | ((value & 0x3333) << 2);
+       value = ((value & 0xF0F0) >> 4) | ((value & 0x0F0F) << 4);
+       return ByteReverse(value);
+}
+
+inline word32 BitReverse(word32 value)
+{
+       value = ((value & 0xAAAAAAAA) >> 1) | ((value & 0x55555555) << 1);
+       value = ((value & 0xCCCCCCCC) >> 2) | ((value & 0x33333333) << 2);
+       value = ((value & 0xF0F0F0F0) >> 4) | ((value & 0x0F0F0F0F) << 4);
+       return ByteReverse(value);
+}
+
+inline word64 BitReverse(word64 value)
+{
+#if CRYPTOPP_BOOL_SLOW_WORD64
+       return (word64(BitReverse(word32(value))) << 32) | BitReverse(word32(value>>32));
+#else
+       value = ((value & W64LIT(0xAAAAAAAAAAAAAAAA)) >> 1) | ((value & W64LIT(0x5555555555555555)) << 1);
+       value = ((value & W64LIT(0xCCCCCCCCCCCCCCCC)) >> 2) | ((value & W64LIT(0x3333333333333333)) << 2);
+       value = ((value & W64LIT(0xF0F0F0F0F0F0F0F0)) >> 4) | ((value & W64LIT(0x0F0F0F0F0F0F0F0F)) << 4);
+       return ByteReverse(value);
+#endif
+}
+
+template <class T>
+inline T BitReverse(T value)
+{
+       if (sizeof(T) == 1)
+               return (T)BitReverse((byte)value);
+       else if (sizeof(T) == 2)
+               return (T)BitReverse((word16)value);
+       else if (sizeof(T) == 4)
+               return (T)BitReverse((word32)value);
+       else
+       {
+               assert(sizeof(T) == 8);
+               return (T)BitReverse((word64)value);
+       }
+}
+
+template <class T>
+inline T ConditionalByteReverse(ByteOrder order, T value)
+{
+       return NativeByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+template <class T>
+void ByteReverse(T *out, const T *in, size_t byteCount)
+{
+       assert(byteCount % sizeof(T) == 0);
+       size_t count = byteCount/sizeof(T);
+       for (size_t i=0; i<count; i++)
+               out[i] = ByteReverse(in[i]);
+}
+
+template <class T>
+inline void ConditionalByteReverse(ByteOrder order, T *out, const T *in, size_t byteCount)
+{
+       if (!NativeByteOrderIs(order))
+               ByteReverse(out, in, byteCount);
+       else if (in != out)
+               memcpy_s(out, byteCount, in, byteCount);
+}
+
+template <class T>
+inline void GetUserKey(ByteOrder order, T *out, size_t outlen, const byte *in, size_t inlen)
+{
+       const size_t U = sizeof(T);
+       assert(inlen <= outlen*U);
+       memcpy_s(out, outlen*U, in, inlen);
+       memset_z((byte *)out+inlen, 0, outlen*U-inlen);
+       ConditionalByteReverse(order, out, out, RoundUpToMultipleOf(inlen, U));
+}
+
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+inline byte UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const byte *)
+{
+       return block[0];
+}
+
+inline word16 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word16 *)
+{
+       return (order == BIG_ENDIAN_ORDER)
+               ? block[1] | (block[0] << 8)
+               : block[0] | (block[1] << 8);
+}
+
+inline word32 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const word32 *)
+{
+       return (order == BIG_ENDIAN_ORDER)
+               ? word32(block[3]) | (word32(block[2]) << 8) | (word32(block[1]) << 16) | (word32(block[0]) << 24)
+               : word32(block[0]) | (word32(block[1]) << 8) | (word32(block[2]) << 16) | (word32(block[3]) << 24);
+}
+
+inline word64 UnalignedGetWordNonTemplate(ByteOrder order, const byte *block, const 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));
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, byte value, const byte *xorBlock)
+{
+       block[0] = xorBlock ? (value ^ xorBlock[0]) : value;
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word16 value, const byte *xorBlock)
+{
+       if (order == BIG_ENDIAN_ORDER)
+       {
+               if (xorBlock)
+               {
+                       block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+               }
+               else
+               {
+                       block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+               }
+       }
+       else
+       {
+               if (xorBlock)
+               {
+                       block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+                       block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+               }
+               else
+               {
+                       block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+                       block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+               }
+       }
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word32 value, const byte *xorBlock)
+{
+       if (order == BIG_ENDIAN_ORDER)
+       {
+               if (xorBlock)
+               {
+                       block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+                       block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+               }
+               else
+               {
+                       block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+                       block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+               }
+       }
+       else
+       {
+               if (xorBlock)
+               {
+                       block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+                       block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+               }
+               else
+               {
+                       block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+                       block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+               }
+       }
+}
+
+inline void UnalignedPutWordNonTemplate(ByteOrder order, byte *block, word64 value, const byte *xorBlock)
+{
+       if (order == BIG_ENDIAN_ORDER)
+       {
+               if (xorBlock)
+               {
+                       block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+                       block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+                       block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+                       block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+                       block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+                       block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+               }
+               else
+               {
+                       block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+                       block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+                       block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+                       block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+                       block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+                       block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+               }
+       }
+       else
+       {
+               if (xorBlock)
+               {
+                       block[0] = xorBlock[0] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+                       block[1] = xorBlock[1] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[2] = xorBlock[2] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[3] = xorBlock[3] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+                       block[4] = xorBlock[4] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+                       block[5] = xorBlock[5] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+                       block[6] = xorBlock[6] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+                       block[7] = xorBlock[7] ^ CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+               }
+               else
+               {
+                       block[0] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 0);
+                       block[1] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 1);
+                       block[2] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 2);
+                       block[3] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 3);
+                       block[4] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 4);
+                       block[5] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 5);
+                       block[6] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 6);
+                       block[7] = CRYPTOPP_GET_BYTE_AS_BYTE(value, 7);
+               }
+       }
+}
+#endif // #ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+
+template <class T>
+inline T GetWord(bool assumeAligned, ByteOrder order, const byte *block)
+{
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+       if (!assumeAligned)
+               return UnalignedGetWordNonTemplate(order, block, (T*)NULL);
+       assert(IsAligned<T>(block));
+#endif
+       return ConditionalByteReverse(order, *reinterpret_cast<const T *>(block));
+}
+
+template <class T>
+inline void GetWord(bool assumeAligned, ByteOrder order, T &result, const byte *block)
+{
+       result = GetWord<T>(assumeAligned, order, block);
+}
+
+template <class T>
+inline void PutWord(bool assumeAligned, ByteOrder order, byte *block, T value, const byte *xorBlock = NULL)
+{
+#ifndef CRYPTOPP_ALLOW_UNALIGNED_DATA_ACCESS
+       if (!assumeAligned)
+               return UnalignedPutWordNonTemplate(order, block, value, xorBlock);
+       assert(IsAligned<T>(block));
+       assert(IsAligned<T>(xorBlock));
+#endif
+       *reinterpret_cast<T *>(block) = ConditionalByteReverse(order, value) ^ (xorBlock ? *reinterpret_cast<const T *>(xorBlock) : 0);
+}
+
+template <class T, class B, bool A=false>
+class GetBlock
+{
+public:
+       GetBlock(const void *block)
+               : m_block((const byte *)block) {}
+
+       template <class U>
+       inline GetBlock<T, B, A> & operator()(U &x)
+       {
+               CRYPTOPP_COMPILE_ASSERT(sizeof(U) >= sizeof(T));
+               x = GetWord<T>(A, B::ToEnum(), m_block);
+               m_block += sizeof(T);
+               return *this;
+       }
+
+private:
+       const byte *m_block;
+};
+
+template <class T, class B, bool A=false>
+class PutBlock
+{
+public:
+       PutBlock(const void *xorBlock, void *block)
+               : m_xorBlock((const byte *)xorBlock), m_block((byte *)block) {}
+
+       template <class U>
+       inline PutBlock<T, B, A> & operator()(U x)
+       {
+               PutWord(A, B::ToEnum(), m_block, (T)x, m_xorBlock);
+               m_block += sizeof(T);
+               if (m_xorBlock)
+                       m_xorBlock += sizeof(T);
+               return *this;
+       }
+
+private:
+       const byte *m_xorBlock;
+       byte *m_block;
+};
+
+template <class T, class B, bool GA=false, bool PA=false>
+struct BlockGetAndPut
+{
+       // function needed because of C++ grammatical ambiguity between expression-statements and declarations
+       static inline GetBlock<T, B, GA> Get(const void *block) {return GetBlock<T, B, GA>(block);}
+       typedef PutBlock<T, B, PA> Put;
+};
+
+template <class T>
+std::string WordToString(T value, ByteOrder order = BIG_ENDIAN_ORDER)
+{
+       if (!NativeByteOrderIs(order))
+               value = ByteReverse(value);
+
+       return std::string((char *)&value, sizeof(value));
+}
+
+template <class T>
+T StringToWord(const std::string &str, ByteOrder order = BIG_ENDIAN_ORDER)
+{
+       T value = 0;
+       memcpy_s(&value, sizeof(value), str.data(), UnsignedMin(str.size(), sizeof(value)));
+       return NativeByteOrderIs(order) ? value : ByteReverse(value);
+}
+
+// ************** help remove warning on g++ ***************
+
+template <bool overflow> struct SafeShifter;
+
+template<> struct SafeShifter<true>
+{
+       template <class T>
+       static inline T RightShift(T value, unsigned int bits)
+       {
+               return 0;
+       }
+
+       template <class T>
+       static inline T LeftShift(T value, unsigned int bits)
+       {
+               return 0;
+       }
+};
+
+template<> struct SafeShifter<false>
+{
+       template <class T>
+       static inline T RightShift(T value, unsigned int bits)
+       {
+               return value >> bits;
+       }
+
+       template <class T>
+       static inline T LeftShift(T value, unsigned int bits)
+       {
+               return value << bits;
+       }
+};
+
+template <unsigned int bits, class T>
+inline T SafeRightShift(T value)
+{
+       return SafeShifter<(bits>=(8*sizeof(T)))>::RightShift(value, bits);
+}
+
+template <unsigned int bits, class T>
+inline T SafeLeftShift(T value)
+{
+       return SafeShifter<(bits>=(8*sizeof(T)))>::LeftShift(value, bits);
+}
+
+// ************** use one buffer for multiple data members ***************
+
+#define CRYPTOPP_BLOCK_1(n, t, s) t* m_##n() {return (t *)(m_aggregate+0);}     size_t SS1() {return       sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_2(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS1());} size_t SS2() {return SS1()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_3(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS2());} size_t SS3() {return SS2()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_4(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS3());} size_t SS4() {return SS3()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_5(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS4());} size_t SS5() {return SS4()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_6(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS5());} size_t SS6() {return SS5()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_7(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS6());} size_t SS7() {return SS6()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCK_8(n, t, s) t* m_##n() {return (t *)(m_aggregate+SS7());} size_t SS8() {return SS7()+sizeof(t)*(s);} size_t m_##n##Size() {return (s);}
+#define CRYPTOPP_BLOCKS_END(i) size_t SST() {return SS##i();} void AllocateBlocks() {m_aggregate.New(SST());} AlignedSecByteBlock m_aggregate;
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/pch.h b/cryptopp/include/cryptopp/pch.h
new file mode 100644 (file)
index 0000000..418c390
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef CRYPTOPP_PCH_H
+#define CRYPTOPP_PCH_H
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+
+       #include "cpu.h"
+
+#else
+
+       #include "config.h"
+
+       #ifdef USE_PRECOMPILED_HEADERS
+               #include "simple.h"
+               #include "secblock.h"
+               #include "misc.h"
+               #include "smartptr.h"
+       #endif
+
+#endif
+
+#endif
diff --git a/cryptopp/include/cryptopp/secblock.h b/cryptopp/include/cryptopp/secblock.h
new file mode 100644 (file)
index 0000000..6433f97
--- /dev/null
@@ -0,0 +1,501 @@
+// secblock.h - written and placed in the public domain by Wei Dai
+
+#ifndef CRYPTOPP_SECBLOCK_H
+#define CRYPTOPP_SECBLOCK_H
+
+#include "cryptopp/config.h"
+#include "cryptopp/misc.h"
+#include <assert.h>
+
+#if defined(CRYPTOPP_MEMALIGN_AVAILABLE) || defined(CRYPTOPP_MM_MALLOC_AVAILABLE) || defined(QNX)
+       #include <malloc.h>
+#else
+       #include <stdlib.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// ************** secure memory allocation ***************
+
+template<class T>
+class AllocatorBase
+{
+public:
+       typedef T value_type;
+       typedef size_t size_type;
+#ifdef CRYPTOPP_MSVCRT6
+       typedef ptrdiff_t difference_type;
+#else
+       typedef std::ptrdiff_t difference_type;
+#endif
+       typedef T * pointer;
+       typedef const T * const_pointer;
+       typedef T & reference;
+       typedef const T & const_reference;
+
+       pointer address(reference r) const {return (&r);}
+       const_pointer address(const_reference r) const {return (&r); }
+       void construct(pointer p, const T& val) {new (p) T(val);}
+       void destroy(pointer p) {p->~T();}
+       size_type max_size() const {return ~size_type(0)/sizeof(T);}    // switch to std::numeric_limits<T>::max later
+
+protected:
+       static void CheckSize(size_t n)
+       {
+               if (n > ~size_t(0) / sizeof(T))
+                       throw InvalidArgument("AllocatorBase: requested size would cause integer overflow");
+       }
+};
+
+#define CRYPTOPP_INHERIT_ALLOCATOR_TYPES       \
+typedef typename AllocatorBase<T>::value_type value_type;\
+typedef typename AllocatorBase<T>::size_type size_type;\
+typedef typename AllocatorBase<T>::difference_type difference_type;\
+typedef typename AllocatorBase<T>::pointer pointer;\
+typedef typename AllocatorBase<T>::const_pointer const_pointer;\
+typedef typename AllocatorBase<T>::reference reference;\
+typedef typename AllocatorBase<T>::const_reference const_reference;
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+// this pragma causes an internal compiler error if placed immediately before std::swap(a, b)
+#pragma warning(push)
+#pragma warning(disable: 4700) // VC60 workaround: don't know how to get rid of this warning
+#endif
+
+template <class T, class A>
+typename A::pointer StandardReallocate(A& a, T *p, typename A::size_type oldSize, typename A::size_type newSize, bool preserve)
+{
+       if (oldSize == newSize)
+               return p;
+
+       if (preserve)
+       {
+               typename A::pointer newPointer = a.allocate(newSize, NULL);
+               memcpy_s(newPointer, sizeof(T)*newSize, p, sizeof(T)*STDMIN(oldSize, newSize));
+               a.deallocate(p, oldSize);
+               return newPointer;
+       }
+       else
+       {
+               a.deallocate(p, oldSize);
+               return a.allocate(newSize, NULL);
+       }
+}
+
+#if defined(_MSC_VER) && (_MSC_VER < 1300)
+#pragma warning(pop)
+#endif
+
+template <class T, bool T_Align16 = false>
+class AllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+       CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+       pointer allocate(size_type n, const void * = NULL)
+       {
+               CheckSize(n);
+               if (n == 0)
+                       return NULL;
+
+               if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16)
+               {
+                       byte *p;
+               #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
+                       while (!(p = (byte *)_mm_malloc(sizeof(T)*n, 16)))
+               #elif defined(CRYPTOPP_MEMALIGN_AVAILABLE)
+                       while (!(p = (byte *)memalign(16, sizeof(T)*n)))
+               #elif defined(CRYPTOPP_MALLOC_ALIGNMENT_IS_16)
+                       while (!(p = (byte *)malloc(sizeof(T)*n)))
+               #else
+                       while (!(p = (byte *)malloc(sizeof(T)*n + 16)))
+               #endif
+                               CallNewHandler();
+
+               #ifdef CRYPTOPP_NO_ALIGNED_ALLOC
+                       size_t adjustment = 16-((size_t)p%16);
+                       p += adjustment;
+                       p[-1] = (byte)adjustment;
+               #endif
+
+                       assert(IsAlignedOn(p, 16));
+                       return (pointer)p;
+               }
+
+               pointer p;
+               while (!(p = (pointer)malloc(sizeof(T)*n)))
+                       CallNewHandler();
+               return p;
+       }
+
+       void deallocate(void *p, size_type n)
+       {
+               memset_z(p, 0, n*sizeof(T));
+
+               if (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16 && n*sizeof(T) >= 16)
+               {
+               #ifdef CRYPTOPP_MM_MALLOC_AVAILABLE
+                       _mm_free(p);
+               #elif defined(CRYPTOPP_NO_ALIGNED_ALLOC)
+                       p = (byte *)p - ((byte *)p)[-1];
+                       free(p);
+               #else
+                       free(p);
+               #endif
+                       return;
+               }
+
+               free(p);
+       }
+
+       pointer reallocate(T *p, size_type oldSize, size_type newSize, bool preserve)
+       {
+               return StandardReallocate(*this, p, oldSize, newSize, preserve);
+       }
+
+       // VS.NET STL enforces the policy of "All STL-compliant allocators have to provide a
+       // template class member called rebind".
+    template <class U> struct rebind { typedef AllocatorWithCleanup<U, T_Align16> other; };
+#if _MSC_VER >= 1500
+       AllocatorWithCleanup() {}
+       template <class U, bool A> AllocatorWithCleanup(const AllocatorWithCleanup<U, A> &) {}
+#endif
+};
+
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<byte>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word16>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word32>;
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word64>;
+#if CRYPTOPP_BOOL_X86
+CRYPTOPP_DLL_TEMPLATE_CLASS AllocatorWithCleanup<word, true>;  // for Integer
+#endif
+
+template <class T>
+class NullAllocator : public AllocatorBase<T>
+{
+public:
+       CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+       pointer allocate(size_type n, const void * = NULL)
+       {
+               assert(false);
+               return NULL;
+       }
+
+       void deallocate(void *p, size_type n)
+       {
+               //// Bitcoin: don't know why this trips, probably a false alarm, depends on the compiler used. 
+               //assert(false);
+       }
+
+       size_type max_size() const {return 0;}
+};
+
+// This allocator can't be used with standard collections because
+// they require that all objects of the same allocator type are equivalent.
+// So this is for use with SecBlock only.
+template <class T, size_t S, class A = NullAllocator<T>, bool T_Align16 = false>
+class FixedSizeAllocatorWithCleanup : public AllocatorBase<T>
+{
+public:
+       CRYPTOPP_INHERIT_ALLOCATOR_TYPES
+
+       FixedSizeAllocatorWithCleanup() : m_allocated(false) {}
+
+       pointer allocate(size_type n)
+       {
+               assert(IsAlignedOn(m_array, 8));
+
+               if (n <= S && !m_allocated)
+               {
+                       m_allocated = true;
+                       return GetAlignedArray();
+               }
+               else
+                       return m_fallbackAllocator.allocate(n);
+       }
+
+       pointer allocate(size_type n, const void *hint)
+       {
+               if (n <= S && !m_allocated)
+               {
+                       m_allocated = true;
+                       return GetAlignedArray();
+               }
+               else
+                       return m_fallbackAllocator.allocate(n, hint);
+       }
+
+       void deallocate(void *p, size_type n)
+       {
+               if (p == GetAlignedArray())
+               {
+                       assert(n <= S);
+                       assert(m_allocated);
+                       m_allocated = false;
+                       memset(p, 0, n*sizeof(T));
+               }
+               else
+                       m_fallbackAllocator.deallocate(p, n);
+       }
+
+       pointer reallocate(pointer p, size_type oldSize, size_type newSize, bool preserve)
+       {
+               if (p == GetAlignedArray() && newSize <= S)
+               {
+                       assert(oldSize <= S);
+                       if (oldSize > newSize)
+                               memset(p + newSize, 0, (oldSize-newSize)*sizeof(T));
+                       return p;
+               }
+
+               pointer newPointer = allocate(newSize, NULL);
+               if (preserve)
+                       memcpy(newPointer, p, sizeof(T)*STDMIN(oldSize, newSize));
+               deallocate(p, oldSize);
+               return newPointer;
+       }
+
+       size_type max_size() const {return STDMAX(m_fallbackAllocator.max_size(), S);}
+
+private:
+#ifdef __BORLANDC__
+       T* GetAlignedArray() {return m_array;}
+       T m_array[S];
+#else
+       T* GetAlignedArray() {return (CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? (T*)(((byte *)m_array) + (0-(size_t)m_array)%16) : m_array;}
+       CRYPTOPP_ALIGN_DATA(8) T m_array[(CRYPTOPP_BOOL_ALIGN16_ENABLED && T_Align16) ? S+8/sizeof(T) : S];
+#endif
+       A m_fallbackAllocator;
+       bool m_allocated;
+};
+
+//! a block of memory allocated using A
+template <class T, class A = AllocatorWithCleanup<T> >
+class SecBlock
+{
+public:
+       typedef typename A::value_type value_type;
+       typedef typename A::pointer iterator;
+       typedef typename A::const_pointer const_iterator;
+       typedef typename A::size_type size_type;
+
+       explicit SecBlock(size_type size=0)
+               : m_size(size) {m_ptr = m_alloc.allocate(size, NULL);}
+       SecBlock(const SecBlock<T, A> &t)
+               : m_size(t.m_size) {m_ptr = m_alloc.allocate(m_size, NULL); memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));}
+       SecBlock(const T *t, size_type len)
+               : m_size(len)
+       {
+               m_ptr = m_alloc.allocate(len, NULL);
+               if (t == NULL)
+                       memset_z(m_ptr, 0, len*sizeof(T));
+               else
+                       memcpy(m_ptr, t, len*sizeof(T));
+       }
+
+       ~SecBlock()
+               {m_alloc.deallocate(m_ptr, m_size);}
+
+#ifdef __BORLANDC__
+       operator T *() const
+               {return (T*)m_ptr;}
+#else
+       operator const void *() const
+               {return m_ptr;}
+       operator void *()
+               {return m_ptr;}
+
+       operator const T *() const
+               {return m_ptr;}
+       operator T *()
+               {return m_ptr;}
+#endif
+
+//     T *operator +(size_type offset)
+//             {return m_ptr+offset;}
+
+//     const T *operator +(size_type offset) const
+//             {return m_ptr+offset;}
+
+//     T& operator[](size_type index)
+//             {assert(index >= 0 && index < m_size); return m_ptr[index];}
+
+//     const T& operator[](size_type index) const
+//             {assert(index >= 0 && index < m_size); return m_ptr[index];}
+
+       iterator begin()
+               {return m_ptr;}
+       const_iterator begin() const
+               {return m_ptr;}
+       iterator end()
+               {return m_ptr+m_size;}
+       const_iterator end() const
+               {return m_ptr+m_size;}
+
+       typename A::pointer data() {return m_ptr;}
+       typename A::const_pointer data() const {return m_ptr;}
+
+       size_type size() const {return m_size;}
+       bool empty() const {return m_size == 0;}
+
+       byte * BytePtr() {return (byte *)m_ptr;}
+       const byte * BytePtr() const {return (const byte *)m_ptr;}
+       size_type SizeInBytes() const {return m_size*sizeof(T);}
+
+       //! set contents and size
+       void Assign(const T *t, size_type len)
+       {
+               New(len);
+               memcpy_s(m_ptr, m_size*sizeof(T), t, len*sizeof(T));
+       }
+
+       //! copy contents and size from another SecBlock
+       void Assign(const SecBlock<T, A> &t)
+       {
+               New(t.m_size);
+               memcpy_s(m_ptr, m_size*sizeof(T), t.m_ptr, m_size*sizeof(T));
+       }
+
+       SecBlock<T, A>& operator=(const SecBlock<T, A> &t)
+       {
+               Assign(t);
+               return *this;
+       }
+
+       // append to this object
+       SecBlock<T, A>& operator+=(const SecBlock<T, A> &t)
+       {
+               size_type oldSize = m_size;
+               Grow(m_size+t.m_size);
+               memcpy_s(m_ptr+oldSize, m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+               return *this;
+       }
+
+       // append operator
+       SecBlock<T, A> operator+(const SecBlock<T, A> &t)
+       {
+               SecBlock<T, A> result(m_size+t.m_size);
+               memcpy_s(result.m_ptr, result.m_size*sizeof(T), m_ptr, m_size*sizeof(T));
+               memcpy_s(result.m_ptr+m_size, t.m_size*sizeof(T), t.m_ptr, t.m_size*sizeof(T));
+               return result;
+       }
+
+       bool operator==(const SecBlock<T, A> &t) const
+       {
+               return m_size == t.m_size && VerifyBufsEqual(m_ptr, t.m_ptr, m_size*sizeof(T));
+       }
+
+       bool operator!=(const SecBlock<T, A> &t) const
+       {
+               return !operator==(t);
+       }
+
+       //! change size, without preserving contents
+       void New(size_type newSize)
+       {
+               m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, false);
+               m_size = newSize;
+       }
+
+       //! change size and set contents to 0
+       void CleanNew(size_type newSize)
+       {
+               New(newSize);
+               memset_z(m_ptr, 0, m_size*sizeof(T));
+       }
+
+       //! change size only if newSize > current size. contents are preserved
+       void Grow(size_type newSize)
+       {
+               if (newSize > m_size)
+               {
+                       m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+                       m_size = newSize;
+               }
+       }
+
+       //! change size only if newSize > current size. contents are preserved and additional area is set to 0
+       void CleanGrow(size_type newSize)
+       {
+               if (newSize > m_size)
+               {
+                       m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+                       memset(m_ptr+m_size, 0, (newSize-m_size)*sizeof(T));
+                       m_size = newSize;
+               }
+       }
+
+       //! change size and preserve contents
+       void resize(size_type newSize)
+       {
+               m_ptr = m_alloc.reallocate(m_ptr, m_size, newSize, true);
+               m_size = newSize;
+       }
+
+       //! swap contents and size with another SecBlock
+       void swap(SecBlock<T, A> &b)
+       {
+               std::swap(m_alloc, b.m_alloc);
+               std::swap(m_size, b.m_size);
+               std::swap(m_ptr, b.m_ptr);
+       }
+
+//private:
+       A m_alloc;
+       size_type m_size;
+       T *m_ptr;
+};
+
+typedef SecBlock<byte> SecByteBlock;
+typedef SecBlock<byte, AllocatorWithCleanup<byte, true> > AlignedSecByteBlock;
+typedef SecBlock<word> SecWordBlock;
+
+//! a SecBlock with fixed size, allocated statically
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S> >
+class FixedSizeSecBlock : public SecBlock<T, A>
+{
+public:
+       explicit FixedSizeSecBlock() : SecBlock<T, A>(S) {}
+};
+
+template <class T, unsigned int S, bool T_Align16 = true>
+class FixedSizeAlignedSecBlock : public FixedSizeSecBlock<T, S, FixedSizeAllocatorWithCleanup<T, S, NullAllocator<T>, T_Align16> >
+{
+};
+
+//! a SecBlock that preallocates size S statically, and uses the heap when this size is exceeded
+template <class T, unsigned int S, class A = FixedSizeAllocatorWithCleanup<T, S, AllocatorWithCleanup<T> > >
+class SecBlockWithHint : public SecBlock<T, A>
+{
+public:
+       explicit SecBlockWithHint(size_t size) : SecBlock<T, A>(size) {}
+};
+
+template<class T, bool A, class U, bool B>
+inline bool operator==(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (true);}
+template<class T, bool A, class U, bool B>
+inline bool operator!=(const CryptoPP::AllocatorWithCleanup<T, A>&, const CryptoPP::AllocatorWithCleanup<U, B>&) {return (false);}
+
+NAMESPACE_END
+
+NAMESPACE_BEGIN(std)
+template <class T, class A>
+inline void swap(CryptoPP::SecBlock<T, A> &a, CryptoPP::SecBlock<T, A> &b)
+{
+       a.swap(b);
+}
+
+#if defined(_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) || (defined(_STLPORT_VERSION) && !defined(_STLP_MEMBER_TEMPLATE_CLASSES))
+// working for STLport 5.1.3 and MSVC 6 SP5
+template <class _Tp1, class _Tp2>
+inline CryptoPP::AllocatorWithCleanup<_Tp2>&
+__stl_alloc_rebind(CryptoPP::AllocatorWithCleanup<_Tp1>& __a, const _Tp2*)
+{
+       return (CryptoPP::AllocatorWithCleanup<_Tp2>&)(__a);
+}
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/sha.h b/cryptopp/include/cryptopp/sha.h
new file mode 100644 (file)
index 0000000..8d0dbfc
--- /dev/null
@@ -0,0 +1,63 @@
+#ifndef CRYPTOPP_SHA_H
+#define CRYPTOPP_SHA_H
+
+#include "cryptopp/iterhash.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+/// <a href="http://www.weidai.com/scan-mirror/md.html#SHA-1">SHA-1</a>
+class CRYPTOPP_DLL SHA1 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 20, SHA1>
+{
+public:
+       static void CRYPTOPP_API InitState(HashWordType *state);
+       static void CRYPTOPP_API Transform(word32 *digest, const word32 *data);
+       static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-1";}
+};
+
+typedef SHA1 SHA;      // for backwards compatibility
+
+//! implements the SHA-256 standard
+class CRYPTOPP_DLL SHA256 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SHA256, 32, true>
+{
+public:
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+       size_t HashMultipleBlocks(const word32 *input, size_t length);
+#endif
+       static void CRYPTOPP_API InitState(HashWordType *state);
+       static void CRYPTOPP_API Transform(word32 *digest, const word32 *data);
+       static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-256";}
+};
+
+//! implements the SHA-224 standard
+class CRYPTOPP_DLL SHA224 : public IteratedHashWithStaticTransform<word32, BigEndian, 64, 32, SHA224, 28, true>
+{
+public:
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+       size_t HashMultipleBlocks(const word32 *input, size_t length);
+#endif
+       static void CRYPTOPP_API InitState(HashWordType *state);
+       static void CRYPTOPP_API Transform(word32 *digest, const word32 *data) {SHA256::Transform(digest, data);}
+       static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-224";}
+};
+
+//! implements the SHA-512 standard
+class CRYPTOPP_DLL SHA512 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA512, 64, CRYPTOPP_BOOL_X86>
+{
+public:
+       static void CRYPTOPP_API InitState(HashWordType *state);
+       static void CRYPTOPP_API Transform(word64 *digest, const word64 *data);
+       static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-512";}
+};
+
+//! implements the SHA-384 standard
+class CRYPTOPP_DLL SHA384 : public IteratedHashWithStaticTransform<word64, BigEndian, 128, 64, SHA384, 48, CRYPTOPP_BOOL_X86>
+{
+public:
+       static void CRYPTOPP_API InitState(HashWordType *state);
+       static void CRYPTOPP_API Transform(word64 *digest, const word64 *data) {SHA512::Transform(digest, data);}
+       static const char * CRYPTOPP_API StaticAlgorithmName() {return "SHA-384";}
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/simple.h b/cryptopp/include/cryptopp/simple.h
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/cryptopp/include/cryptopp/smartptr.h b/cryptopp/include/cryptopp/smartptr.h
new file mode 100644 (file)
index 0000000..fa0daec
--- /dev/null
@@ -0,0 +1,223 @@
+#ifndef CRYPTOPP_SMARTPTR_H
+#define CRYPTOPP_SMARTPTR_H
+
+#include "cryptopp/config.h"
+#include <algorithm>
+
+NAMESPACE_BEGIN(CryptoPP)
+
+template <class T> class simple_ptr
+{
+public:
+       simple_ptr() : m_p(NULL) {}
+       ~simple_ptr() {delete m_p;}
+       T *m_p;
+};
+
+template <class T> class member_ptr
+{
+public:
+       explicit member_ptr(T *p = NULL) : m_p(p) {}
+
+       ~member_ptr();
+
+       const T& operator*() const { return *m_p; }
+       T& operator*() { return *m_p; }
+
+       const T* operator->() const { return m_p; }
+       T* operator->() { return m_p; }
+
+       const T* get() const { return m_p; }
+       T* get() { return m_p; }
+
+       T* release()
+       {
+               T *old_p = m_p;
+               m_p = 0;
+               return old_p;
+       } 
+
+       void reset(T *p = 0);
+
+protected:
+       member_ptr(const member_ptr<T>& rhs);           // copy not allowed
+       void operator=(const member_ptr<T>& rhs);       // assignment not allowed
+
+       T *m_p;
+};
+
+template <class T> member_ptr<T>::~member_ptr() {delete m_p;}
+template <class T> void member_ptr<T>::reset(T *p) {delete m_p; m_p = p;}
+
+// ********************************************************
+
+template<class T> class value_ptr : public member_ptr<T>
+{
+public:
+       value_ptr(const T &obj) : member_ptr<T>(new T(obj)) {}
+       value_ptr(T *p = NULL) : member_ptr<T>(p) {}
+       value_ptr(const value_ptr<T>& rhs)
+               : member_ptr<T>(rhs.m_p ? new T(*rhs.m_p) : NULL) {}
+
+       value_ptr<T>& operator=(const value_ptr<T>& rhs);
+       bool operator==(const value_ptr<T>& rhs)
+       {
+               return (!this->m_p && !rhs.m_p) || (this->m_p && rhs.m_p && *this->m_p == *rhs.m_p);
+       }
+};
+
+template <class T> value_ptr<T>& value_ptr<T>::operator=(const value_ptr<T>& rhs)
+{
+       T *old_p = this->m_p;
+       this->m_p = rhs.m_p ? new T(*rhs.m_p) : NULL;
+       delete old_p;
+       return *this;
+}
+
+// ********************************************************
+
+template<class T> class clonable_ptr : public member_ptr<T>
+{
+public:
+       clonable_ptr(const T &obj) : member_ptr<T>(obj.Clone()) {}
+       clonable_ptr(T *p = NULL) : member_ptr<T>(p) {}
+       clonable_ptr(const clonable_ptr<T>& rhs)
+               : member_ptr<T>(rhs.m_p ? rhs.m_p->Clone() : NULL) {}
+
+       clonable_ptr<T>& operator=(const clonable_ptr<T>& rhs);
+};
+
+template <class T> clonable_ptr<T>& clonable_ptr<T>::operator=(const clonable_ptr<T>& rhs)
+{
+       T *old_p = this->m_p;
+       this->m_p = rhs.m_p ? rhs.m_p->Clone() : NULL;
+       delete old_p;
+       return *this;
+}
+
+// ********************************************************
+
+template<class T> class counted_ptr
+{
+public:
+       explicit counted_ptr(T *p = 0);
+       counted_ptr(const T &r) : m_p(0) {attach(r);}
+       counted_ptr(const counted_ptr<T>& rhs);
+
+       ~counted_ptr();
+
+       const T& operator*() const { return *m_p; }
+       T& operator*() { return *m_p; }
+
+       const T* operator->() const { return m_p; }
+       T* operator->() { return get(); }
+
+       const T* get() const { return m_p; }
+       T* get();
+
+       void attach(const T &p);
+
+       counted_ptr<T> & operator=(const counted_ptr<T>& rhs);
+
+private:
+       T *m_p;
+};
+
+template <class T> counted_ptr<T>::counted_ptr(T *p)
+       : m_p(p) 
+{
+       if (m_p)
+               m_p->m_referenceCount = 1;
+}
+
+template <class T> counted_ptr<T>::counted_ptr(const counted_ptr<T>& rhs)
+       : m_p(rhs.m_p)
+{
+       if (m_p)
+               m_p->m_referenceCount++;
+}
+
+template <class T> counted_ptr<T>::~counted_ptr()
+{
+       if (m_p && --m_p->m_referenceCount == 0)
+               delete m_p;
+}
+
+template <class T> void counted_ptr<T>::attach(const T &r)
+{
+       if (m_p && --m_p->m_referenceCount == 0)
+               delete m_p;
+       if (r.m_referenceCount == 0)
+       {
+               m_p = r.clone();
+               m_p->m_referenceCount = 1;
+       }
+       else
+       {
+               m_p = const_cast<T *>(&r);
+               m_p->m_referenceCount++;
+       }
+}
+
+template <class T> T* counted_ptr<T>::get()
+{
+       if (m_p && m_p->m_referenceCount > 1)
+       {
+               T *temp = m_p->clone();
+               m_p->m_referenceCount--;
+               m_p = temp;
+               m_p->m_referenceCount = 1;
+       }
+       return m_p;
+}
+
+template <class T> counted_ptr<T> & counted_ptr<T>::operator=(const counted_ptr<T>& rhs)
+{
+       if (m_p != rhs.m_p)
+       {
+               if (m_p && --m_p->m_referenceCount == 0)
+                       delete m_p;
+               m_p = rhs.m_p;
+               if (m_p)
+                       m_p->m_referenceCount++;
+       }
+       return *this;
+}
+
+// ********************************************************
+
+template <class T> class vector_member_ptrs
+{
+public:
+       vector_member_ptrs(size_t size=0)
+               : m_size(size), m_ptr(new member_ptr<T>[size]) {}
+       ~vector_member_ptrs()
+               {delete [] this->m_ptr;}
+
+       member_ptr<T>& operator[](size_t index)
+               {assert(index<this->m_size); return this->m_ptr[index];}
+       const member_ptr<T>& operator[](size_t index) const
+               {assert(index<this->m_size); return this->m_ptr[index];}
+
+       size_t size() const {return this->m_size;}
+       void resize(size_t newSize)
+       {
+               member_ptr<T> *newPtr = new member_ptr<T>[newSize];
+               for (size_t i=0; i<this->m_size && i<newSize; i++)
+                       newPtr[i].reset(this->m_ptr[i].release());
+               delete [] this->m_ptr;
+               this->m_size = newSize;
+               this->m_ptr = newPtr;
+       }
+
+private:
+       vector_member_ptrs(const vector_member_ptrs<T> &c);     // copy not allowed
+       void operator=(const vector_member_ptrs<T> &x);         // assignment not allowed
+
+       size_t m_size;
+       member_ptr<T> *m_ptr;
+};
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/include/cryptopp/stdcpp.h b/cryptopp/include/cryptopp/stdcpp.h
new file mode 100644 (file)
index 0000000..9a468ab
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef CRYPTOPP_STDCPP_H
+#define CRYPTOPP_STDCPP_H
+
+#include <stddef.h>
+#include <assert.h>
+#include <limits.h>
+#include <memory>
+#include <string>
+#include <exception>
+#include <typeinfo>
+
+
+#ifdef _MSC_VER
+#include <string.h>    // CodeWarrior doesn't have memory.h
+#include <algorithm>
+#include <map>
+#include <vector>
+
+// re-disable this
+#pragma warning(disable: 4231)
+#endif
+
+#if defined(_MSC_VER) && defined(_CRTAPI1)
+#define CRYPTOPP_MSVCRT6
+#endif
+
+#endif
diff --git a/cryptopp/src/cpu.cpp b/cryptopp/src/cpu.cpp
new file mode 100644 (file)
index 0000000..d36d325
--- /dev/null
@@ -0,0 +1,199 @@
+// cpu.cpp - written and placed in the public domain by Wei Dai
+
+#include "cryptopp/pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+
+#include "cryptopp/cpu.h"
+#include "cryptopp/misc.h"
+#include <algorithm>
+
+#ifdef __GNUC__
+#include <signal.h>
+#include <setjmp.h>
+#endif
+
+#ifdef CRYPTOPP_MSVC6PP_OR_LATER
+#include <emmintrin.h>
+#endif
+
+NAMESPACE_BEGIN(CryptoPP)
+
+#ifdef CRYPTOPP_X86_ASM_AVAILABLE
+
+#ifndef _MSC_VER
+typedef void (*SigHandler)(int);
+
+static jmp_buf s_jmpNoCPUID;
+static void SigIllHandlerCPUID(int)
+{
+       longjmp(s_jmpNoCPUID, 1);
+}
+#endif
+
+bool CpuId(word32 input, word32 *output)
+{
+#ifdef _MSC_VER
+    __try
+       {
+               __asm
+               {
+                       mov eax, input
+                       cpuid
+                       mov edi, output
+                       mov [edi], eax
+                       mov [edi+4], ebx
+                       mov [edi+8], ecx
+                       mov [edi+12], edx
+               }
+       }
+    __except (1)
+       {
+               return false;
+    }
+       return true;
+#else
+       SigHandler oldHandler = signal(SIGILL, SigIllHandlerCPUID);
+       if (oldHandler == SIG_ERR)
+               return false;
+
+       bool result = true;
+       if (setjmp(s_jmpNoCPUID))
+               result = false;
+       else
+       {
+               __asm__
+               (
+                       // save ebx in case -fPIC is being used
+#if CRYPTOPP_BOOL_X86
+                       "push %%ebx; cpuid; mov %%ebx, %%edi; pop %%ebx"
+#else
+                       "pushq %%rbx; cpuid; mov %%ebx, %%edi; popq %%rbx"
+#endif
+                       : "=a" (output[0]), "=D" (output[1]), "=c" (output[2]), "=d" (output[3])
+                       : "a" (input)
+               );
+       }
+
+       signal(SIGILL, oldHandler);
+       return result;
+#endif
+}
+
+#ifndef _MSC_VER
+static jmp_buf s_jmpNoSSE2;
+static void SigIllHandlerSSE2(int)
+{
+       longjmp(s_jmpNoSSE2, 1);
+}
+#endif
+
+#elif _MSC_VER >= 1400 && CRYPTOPP_BOOL_X64
+
+bool CpuId(word32 input, word32 *output)
+{
+       __cpuid((int *)output, input);
+       return true;
+}
+
+#endif
+
+#ifdef CRYPTOPP_CPUID_AVAILABLE
+
+static bool TrySSE2()
+{
+#if CRYPTOPP_BOOL_X64
+       return true;
+#elif defined(_MSC_VER)
+    __try
+       {
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+        AS2(por xmm0, xmm0)        // executing SSE2 instruction
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+               __mm128i x = _mm_setzero_si128();
+               return _mm_cvtsi128_si32(x) == 0;
+#endif
+       }
+    __except (1)
+       {
+               return false;
+    }
+       return true;
+#elif defined(__GNUC__)
+       SigHandler oldHandler = signal(SIGILL, SigIllHandlerSSE2);
+       if (oldHandler == SIG_ERR)
+               return false;
+
+       bool result = true;
+       if (setjmp(s_jmpNoSSE2))
+               result = false;
+       else
+       {
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+               __asm __volatile ("por %xmm0, %xmm0");
+#elif CRYPTOPP_BOOL_SSE2_INTRINSICS_AVAILABLE
+               __mm128i x = _mm_setzero_si128();
+               result = _mm_cvtsi128_si32(x) == 0;
+#endif
+       }
+
+       signal(SIGILL, oldHandler);
+       return result;
+#else
+       return false;
+#endif
+}
+
+bool g_x86DetectionDone = false;
+bool g_hasISSE = false, g_hasSSE2 = false, g_hasSSSE3 = false, g_hasMMX = false, g_isP4 = false;
+word32 g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+void DetectX86Features()
+{
+       word32 cpuid[4], cpuid1[4];
+       if (!CpuId(0, cpuid))
+               return;
+       if (!CpuId(1, cpuid1))
+               return;
+
+       g_hasMMX = (cpuid1[3] & (1 << 23)) != 0;
+       if ((cpuid1[3] & (1 << 26)) != 0)
+               g_hasSSE2 = TrySSE2();
+       g_hasSSSE3 = g_hasSSE2 && (cpuid1[2] & (1<<9));
+
+       if ((cpuid1[3] & (1 << 25)) != 0)
+               g_hasISSE = true;
+       else
+       {
+               word32 cpuid2[4];
+               CpuId(0x080000000, cpuid2);
+               if (cpuid2[0] >= 0x080000001)
+               {
+                       CpuId(0x080000001, cpuid2);
+                       g_hasISSE = (cpuid2[3] & (1 << 22)) != 0;
+               }
+       }
+
+       std::swap(cpuid[2], cpuid[3]);
+       if (memcmp(cpuid+1, "GenuineIntel", 12) == 0)
+       {
+               g_isP4 = ((cpuid1[0] >> 8) & 0xf) == 0xf;
+               g_cacheLineSize = 8 * GETBYTE(cpuid1[1], 1);
+       }
+       else if (memcmp(cpuid+1, "AuthenticAMD", 12) == 0)
+       {
+               CpuId(0x80000005, cpuid);
+               g_cacheLineSize = GETBYTE(cpuid[2], 0);
+       }
+
+       if (!g_cacheLineSize)
+               g_cacheLineSize = CRYPTOPP_L1_CACHE_LINE_SIZE;
+
+       g_x86DetectionDone = true;
+}
+
+#endif
+
+NAMESPACE_END
+
+#endif
diff --git a/cryptopp/src/sha.cpp b/cryptopp/src/sha.cpp
new file mode 100644 (file)
index 0000000..1ff6c0b
--- /dev/null
@@ -0,0 +1,899 @@
+// sha.cpp - modified by Wei Dai from Steve Reid's public domain sha1.c
+
+// Steve Reid implemented SHA-1. Wei Dai implemented SHA-2.
+// Both are in the public domain.
+
+// use "cl /EP /P /DCRYPTOPP_GENERATE_X64_MASM sha.cpp" to generate MASM code
+
+#include "cryptopp/pch.h"
+
+#ifndef CRYPTOPP_IMPORTS
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#include "cryptopp/sha.h"
+#include "cryptopp/misc.h"
+#include "cryptopp/cpu.h"
+
+NAMESPACE_BEGIN(CryptoPP)
+
+// start of Steve Reid's code
+
+#define blk0(i) (W[i] = data[i])
+#define blk1(i) (W[i&15] = rotlFixed(W[(i+13)&15]^W[(i+8)&15]^W[(i+2)&15]^W[i&15],1))
+
+void SHA1::InitState(HashWordType *state)
+{
+       state[0] = 0x67452301L;
+       state[1] = 0xEFCDAB89L;
+       state[2] = 0x98BADCFEL;
+       state[3] = 0x10325476L;
+       state[4] = 0xC3D2E1F0L;
+}
+
+#define f1(x,y,z) (z^(x&(y^z)))
+#define f2(x,y,z) (x^y^z)
+#define f3(x,y,z) ((x&y)|(z&(x|y)))
+#define f4(x,y,z) (x^y^z)
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=f1(w,x,y)+blk0(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R1(v,w,x,y,z,i) z+=f1(w,x,y)+blk1(i)+0x5A827999+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R2(v,w,x,y,z,i) z+=f2(w,x,y)+blk1(i)+0x6ED9EBA1+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R3(v,w,x,y,z,i) z+=f3(w,x,y)+blk1(i)+0x8F1BBCDC+rotlFixed(v,5);w=rotlFixed(w,30);
+#define R4(v,w,x,y,z,i) z+=f4(w,x,y)+blk1(i)+0xCA62C1D6+rotlFixed(v,5);w=rotlFixed(w,30);
+
+void SHA1::Transform(word32 *state, const word32 *data)
+{
+       word32 W[16];
+    /* Copy context->state[] to working vars */
+    word32 a = state[0];
+    word32 b = state[1];
+    word32 c = state[2];
+    word32 d = state[3];
+    word32 e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+}
+
+// end of Steve Reid's code
+
+// *************************************************************
+
+void SHA224::InitState(HashWordType *state)
+{
+       static const word32 s[8] = {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
+       memcpy(state, s, sizeof(s));
+}
+
+void SHA256::InitState(HashWordType *state)
+{
+       static const word32 s[8] = {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+       memcpy(state, s, sizeof(s));
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+CRYPTOPP_ALIGN_DATA(16) extern const word32 SHA256_K[64] CRYPTOPP_SECTION_ALIGN16 = {
+#else
+extern const word32 SHA256_K[64] = {
+#endif
+       0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+       0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+       0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+       0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+       0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+       0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+       0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+       0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+       0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+       0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+       0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+       0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+       0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+       0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+       0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+       0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
+};
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
+
+#pragma warning(disable: 4731) // frame pointer register 'ebp' modified by inline assembly code
+
+static void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+       , ...   // VC60 workaround: prevent VC 6 from inlining this function
+#endif
+       )
+{
+#if defined(_MSC_VER) && (_MSC_VER == 1200)
+       AS2(mov ecx, [state])
+       AS2(mov edx, [data])
+#endif
+
+       #define LOCALS_SIZE     8*4 + 16*4 + 4*WORD_SZ
+       #define H(i)            [BASE+ASM_MOD(1024+7-(i),8)*4]
+       #define G(i)            H(i+1)
+       #define F(i)            H(i+2)
+       #define E(i)            H(i+3)
+       #define D(i)            H(i+4)
+       #define C(i)            H(i+5)
+       #define B(i)            H(i+6)
+       #define A(i)            H(i+7)
+       #define Wt(i)           BASE+8*4+ASM_MOD(1024+15-(i),16)*4
+       #define Wt_2(i)         Wt((i)-2)
+       #define Wt_15(i)        Wt((i)-15)
+       #define Wt_7(i)         Wt((i)-7)
+       #define K_END           [BASE+8*4+16*4+0*WORD_SZ]
+       #define STATE_SAVE      [BASE+8*4+16*4+1*WORD_SZ]
+       #define DATA_SAVE       [BASE+8*4+16*4+2*WORD_SZ]
+       #define DATA_END        [BASE+8*4+16*4+3*WORD_SZ]
+       #define Kt(i)           WORD_REG(si)+(i)*4
+#if CRYPTOPP_BOOL_X86
+       #define BASE            esp+4
+#elif defined(__GNUC__)
+       #define BASE            r8
+#else
+       #define BASE            rsp
+#endif
+
+#define RA0(i, edx, edi)               \
+       AS2(    add edx, [Kt(i)]        )\
+       AS2(    add edx, [Wt(i)]        )\
+       AS2(    add edx, H(i)           )\
+
+#define RA1(i, edx, edi)
+
+#define RB0(i, edx, edi)
+
+#define RB1(i, edx, edi)       \
+       AS2(    mov AS_REG_7d, [Wt_2(i)]        )\
+       AS2(    mov edi, [Wt_15(i)])\
+       AS2(    mov ebx, AS_REG_7d      )\
+       AS2(    shr AS_REG_7d, 10               )\
+       AS2(    ror ebx, 17             )\
+       AS2(    xor AS_REG_7d, ebx      )\
+       AS2(    ror ebx, 2              )\
+       AS2(    xor ebx, AS_REG_7d      )/* s1(W_t-2) */\
+       AS2(    add ebx, [Wt_7(i)])\
+       AS2(    mov AS_REG_7d, edi      )\
+       AS2(    shr AS_REG_7d, 3                )\
+       AS2(    ror edi, 7              )\
+       AS2(    add ebx, [Wt(i)])/* s1(W_t-2) + W_t-7 + W_t-16 */\
+       AS2(    xor AS_REG_7d, edi      )\
+       AS2(    add edx, [Kt(i)])\
+       AS2(    ror edi, 11             )\
+       AS2(    add edx, H(i)   )\
+       AS2(    xor AS_REG_7d, edi      )/* s0(W_t-15) */\
+       AS2(    add AS_REG_7d, ebx      )/* W_t = s1(W_t-2) + W_t-7 + s0(W_t-15) W_t-16*/\
+       AS2(    mov [Wt(i)], AS_REG_7d)\
+       AS2(    add edx, AS_REG_7d      )\
+
+#define ROUND(i, r, eax, ecx, edi, edx)\
+       /* in: edi = E  */\
+       /* unused: eax, ecx, temp: ebx, AS_REG_7d, out: edx = T1 */\
+       AS2(    mov edx, F(i)   )\
+       AS2(    xor edx, G(i)   )\
+       AS2(    and edx, edi    )\
+       AS2(    xor edx, G(i)   )/* Ch(E,F,G) = (G^(E&(F^G))) */\
+       AS2(    mov AS_REG_7d, edi      )\
+       AS2(    ror edi, 6              )\
+       AS2(    ror AS_REG_7d, 25               )\
+       RA##r(i, edx, edi               )/* H + Wt + Kt + Ch(E,F,G) */\
+       AS2(    xor AS_REG_7d, edi      )\
+       AS2(    ror edi, 5              )\
+       AS2(    xor AS_REG_7d, edi      )/* S1(E) */\
+       AS2(    add edx, AS_REG_7d      )/* T1 = S1(E) + Ch(E,F,G) + H + Wt + Kt */\
+       RB##r(i, edx, edi               )/* H + Wt + Kt + Ch(E,F,G) */\
+       /* in: ecx = A, eax = B^C, edx = T1 */\
+       /* unused: edx, temp: ebx, AS_REG_7d, out: eax = A, ecx = B^C, edx = E */\
+       AS2(    mov ebx, ecx    )\
+       AS2(    xor ecx, B(i)   )/* A^B */\
+       AS2(    and eax, ecx    )\
+       AS2(    xor eax, B(i)   )/* Maj(A,B,C) = B^((A^B)&(B^C) */\
+       AS2(    mov AS_REG_7d, ebx      )\
+       AS2(    ror ebx, 2              )\
+       AS2(    add eax, edx    )/* T1 + Maj(A,B,C) */\
+       AS2(    add edx, D(i)   )\
+       AS2(    mov D(i), edx   )\
+       AS2(    ror AS_REG_7d, 22               )\
+       AS2(    xor AS_REG_7d, ebx      )\
+       AS2(    ror ebx, 11             )\
+       AS2(    xor AS_REG_7d, ebx      )\
+       AS2(    add eax, AS_REG_7d      )/* T1 + S0(A) + Maj(A,B,C) */\
+       AS2(    mov H(i), eax   )\
+
+#define SWAP_COPY(i)           \
+       AS2(    mov             WORD_REG(bx), [WORD_REG(dx)+i*WORD_SZ])\
+       AS1(    bswap   WORD_REG(bx))\
+       AS2(    mov             [Wt(i*(1+CRYPTOPP_BOOL_X64)+CRYPTOPP_BOOL_X64)], WORD_REG(bx))
+
+#if defined(__GNUC__)
+       #if CRYPTOPP_BOOL_X64
+               FixedSizeAlignedSecBlock<byte, LOCALS_SIZE> workspace;
+       #endif
+       __asm__ __volatile__
+       (
+       #if CRYPTOPP_BOOL_X64
+               "lea %4, %%r8;"
+       #endif
+       ".intel_syntax noprefix;"
+#elif defined(CRYPTOPP_GENERATE_X64_MASM)
+               ALIGN   8
+       X86_SHA256_HashBlocks   PROC FRAME
+               rex_push_reg rsi
+               push_reg rdi
+               push_reg rbx
+               push_reg rbp
+               alloc_stack(LOCALS_SIZE+8)
+               .endprolog
+               mov rdi, r8
+               lea rsi, [?SHA256_K@CryptoPP@@3QBIB + 48*4]
+#endif
+
+#if CRYPTOPP_BOOL_X86
+       #ifndef __GNUC__
+               AS2(    mov             edi, [len])
+               AS2(    lea             WORD_REG(si), [SHA256_K+48*4])
+       #endif
+       #if !defined(_MSC_VER) || (_MSC_VER < 1400)
+               AS_PUSH_IF86(bx)
+       #endif
+
+       AS_PUSH_IF86(bp)
+       AS2(    mov             ebx, esp)
+       AS2(    and             esp, -16)
+       AS2(    sub             WORD_REG(sp), LOCALS_SIZE)
+       AS_PUSH_IF86(bx)
+#endif
+       AS2(    mov             STATE_SAVE, WORD_REG(cx))
+       AS2(    mov             DATA_SAVE, WORD_REG(dx))
+       AS2(    add             WORD_REG(di), WORD_REG(dx))
+       AS2(    mov             DATA_END, WORD_REG(di))
+       AS2(    mov             K_END, WORD_REG(si))
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#if CRYPTOPP_BOOL_X86
+       AS2(    test    edi, 1)
+       ASJ(    jnz,    2, f)
+#endif
+       AS2(    movdqa  xmm0, XMMWORD_PTR [WORD_REG(cx)+0*16])
+       AS2(    movdqa  xmm1, XMMWORD_PTR [WORD_REG(cx)+1*16])
+#endif
+
+#if CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+       ASJ(    jmp,    0, f)
+#endif
+       ASL(2)  // non-SSE2
+       AS2(    mov             esi, ecx)
+       AS2(    lea             edi, A(0))
+       AS2(    mov             ecx, 8)
+       AS1(    rep movsd)
+       AS2(    mov             esi, K_END)
+       ASJ(    jmp,    3, f)
+#endif
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+       ASL(0)
+       AS2(    movdqa  E(0), xmm1)
+       AS2(    movdqa  A(0), xmm0)
+#endif
+#if CRYPTOPP_BOOL_X86
+       ASL(3)
+#endif
+       AS2(    sub             WORD_REG(si), 48*4)
+       SWAP_COPY(0)    SWAP_COPY(1)    SWAP_COPY(2)    SWAP_COPY(3)
+       SWAP_COPY(4)    SWAP_COPY(5)    SWAP_COPY(6)    SWAP_COPY(7)
+#if CRYPTOPP_BOOL_X86
+       SWAP_COPY(8)    SWAP_COPY(9)    SWAP_COPY(10)   SWAP_COPY(11)
+       SWAP_COPY(12)   SWAP_COPY(13)   SWAP_COPY(14)   SWAP_COPY(15)
+#endif
+       AS2(    mov             edi, E(0))      // E
+       AS2(    mov             eax, B(0))      // B
+       AS2(    xor             eax, C(0))      // B^C
+       AS2(    mov             ecx, A(0))      // A
+
+       ROUND(0, 0, eax, ecx, edi, edx)
+       ROUND(1, 0, ecx, eax, edx, edi)
+       ROUND(2, 0, eax, ecx, edi, edx)
+       ROUND(3, 0, ecx, eax, edx, edi)
+       ROUND(4, 0, eax, ecx, edi, edx)
+       ROUND(5, 0, ecx, eax, edx, edi)
+       ROUND(6, 0, eax, ecx, edi, edx)
+       ROUND(7, 0, ecx, eax, edx, edi)
+       ROUND(8, 0, eax, ecx, edi, edx)
+       ROUND(9, 0, ecx, eax, edx, edi)
+       ROUND(10, 0, eax, ecx, edi, edx)
+       ROUND(11, 0, ecx, eax, edx, edi)
+       ROUND(12, 0, eax, ecx, edi, edx)
+       ROUND(13, 0, ecx, eax, edx, edi)
+       ROUND(14, 0, eax, ecx, edi, edx)
+       ROUND(15, 0, ecx, eax, edx, edi)
+
+       ASL(1)
+       AS2(add WORD_REG(si), 4*16)
+       ROUND(0, 1, eax, ecx, edi, edx)
+       ROUND(1, 1, ecx, eax, edx, edi)
+       ROUND(2, 1, eax, ecx, edi, edx)
+       ROUND(3, 1, ecx, eax, edx, edi)
+       ROUND(4, 1, eax, ecx, edi, edx)
+       ROUND(5, 1, ecx, eax, edx, edi)
+       ROUND(6, 1, eax, ecx, edi, edx)
+       ROUND(7, 1, ecx, eax, edx, edi)
+       ROUND(8, 1, eax, ecx, edi, edx)
+       ROUND(9, 1, ecx, eax, edx, edi)
+       ROUND(10, 1, eax, ecx, edi, edx)
+       ROUND(11, 1, ecx, eax, edx, edi)
+       ROUND(12, 1, eax, ecx, edi, edx)
+       ROUND(13, 1, ecx, eax, edx, edi)
+       ROUND(14, 1, eax, ecx, edi, edx)
+       ROUND(15, 1, ecx, eax, edx, edi)
+       AS2(    cmp             WORD_REG(si), K_END)
+       ASJ(    jne,    1, b)
+
+       AS2(    mov             WORD_REG(dx), DATA_SAVE)
+       AS2(    add             WORD_REG(dx), 64)
+       AS2(    mov             AS_REG_7, STATE_SAVE)
+       AS2(    mov             DATA_SAVE, WORD_REG(dx))
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+#if CRYPTOPP_BOOL_X86
+       AS2(    test    DWORD PTR DATA_END, 1)
+       ASJ(    jnz,    4, f)
+#endif
+       AS2(    movdqa  xmm1, XMMWORD_PTR [AS_REG_7+1*16])
+       AS2(    movdqa  xmm0, XMMWORD_PTR [AS_REG_7+0*16])
+       AS2(    paddd   xmm1, E(0))
+       AS2(    paddd   xmm0, A(0))
+       AS2(    movdqa  [AS_REG_7+1*16], xmm1)
+       AS2(    movdqa  [AS_REG_7+0*16], xmm0)
+       AS2(    cmp             WORD_REG(dx), DATA_END)
+       ASJ(    jl,             0, b)
+#endif
+
+#if CRYPTOPP_BOOL_X86
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+       ASJ(    jmp,    5, f)
+       ASL(4)  // non-SSE2
+#endif
+       AS2(    add             [AS_REG_7+0*4], ecx)    // A
+       AS2(    add             [AS_REG_7+4*4], edi)    // E
+       AS2(    mov             eax, B(0))
+       AS2(    mov             ebx, C(0))
+       AS2(    mov             ecx, D(0))
+       AS2(    add             [AS_REG_7+1*4], eax)
+       AS2(    add             [AS_REG_7+2*4], ebx)
+       AS2(    add             [AS_REG_7+3*4], ecx)
+       AS2(    mov             eax, F(0))
+       AS2(    mov             ebx, G(0))
+       AS2(    mov             ecx, H(0))
+       AS2(    add             [AS_REG_7+5*4], eax)
+       AS2(    add             [AS_REG_7+6*4], ebx)
+       AS2(    add             [AS_REG_7+7*4], ecx)
+       AS2(    mov             ecx, AS_REG_7d)
+       AS2(    cmp             WORD_REG(dx), DATA_END)
+       ASJ(    jl,             2, b)
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+       ASL(5)
+#endif
+#endif
+
+       AS_POP_IF86(sp)
+       AS_POP_IF86(bp)
+       #if !defined(_MSC_VER) || (_MSC_VER < 1400)
+               AS_POP_IF86(bx)
+       #endif
+
+#ifdef CRYPTOPP_GENERATE_X64_MASM
+       add             rsp, LOCALS_SIZE+8
+       pop             rbp
+       pop             rbx
+       pop             rdi
+       pop             rsi
+       ret
+       X86_SHA256_HashBlocks ENDP
+#endif
+
+#ifdef __GNUC__
+       ".att_syntax prefix;"
+       : 
+       : "c" (state), "d" (data), "S" (SHA256_K+48), "D" (len)
+       #if CRYPTOPP_BOOL_X64
+               , "m" (workspace[0])
+       #endif
+       : "memory", "cc", "%eax"
+       #if CRYPTOPP_BOOL_X64
+               , "%rbx", "%r8"
+       #endif
+       );
+#endif
+}
+
+#endif // #if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_GENERATE_X64_MASM)
+
+#ifndef CRYPTOPP_GENERATE_X64_MASM
+
+#ifdef CRYPTOPP_X64_MASM_AVAILABLE
+extern "C" {
+void CRYPTOPP_FASTCALL X86_SHA256_HashBlocks(word32 *state, const word32 *data, size_t len);
+}
+#endif
+
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+
+size_t SHA256::HashMultipleBlocks(const word32 *input, size_t length)
+{
+       X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
+       return length % BLOCKSIZE;
+}
+
+size_t SHA224::HashMultipleBlocks(const word32 *input, size_t length)
+{
+       X86_SHA256_HashBlocks(m_state, input, (length&(size_t(0)-BLOCKSIZE)) - !HasSSE2());
+       return length % BLOCKSIZE;
+}
+
+#endif
+
+#define blk2(i) (W[i&15]+=s1(W[(i-2)&15])+W[(i-7)&15]+s0(W[(i-15)&15]))
+
+#define Ch(x,y,z) (z^(x&(y^z)))
+#define Maj(x,y,z) (y^((x^y)&(y^z)))
+
+#define a(i) T[(0-i)&7]
+#define b(i) T[(1-i)&7]
+#define c(i) T[(2-i)&7]
+#define d(i) T[(3-i)&7]
+#define e(i) T[(4-i)&7]
+#define f(i) T[(5-i)&7]
+#define g(i) T[(6-i)&7]
+#define h(i) T[(7-i)&7]
+
+#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA256_K[i+j]+(j?blk2(i):blk0(i));\
+       d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
+
+// for SHA256
+#define S0(x) (rotrFixed(x,2)^rotrFixed(x,13)^rotrFixed(x,22))
+#define S1(x) (rotrFixed(x,6)^rotrFixed(x,11)^rotrFixed(x,25))
+#define s0(x) (rotrFixed(x,7)^rotrFixed(x,18)^(x>>3))
+#define s1(x) (rotrFixed(x,17)^rotrFixed(x,19)^(x>>10))
+
+void SHA256::Transform(word32 *state, const word32 *data)
+{
+       word32 W[16];
+#if defined(CRYPTOPP_X86_ASM_AVAILABLE) || defined(CRYPTOPP_X64_MASM_AVAILABLE)
+       // this byte reverse is a waste of time, but this function is only called by MDC
+       ByteReverse(W, data, BLOCKSIZE);
+       X86_SHA256_HashBlocks(state, W, BLOCKSIZE - !HasSSE2());
+#else
+       word32 T[8];
+    /* Copy context->state[] to working vars */
+       memcpy(T, state, sizeof(T));
+    /* 64 operations, partially loop unrolled */
+       for (unsigned int j=0; j<64; j+=16)
+       {
+               R( 0); R( 1); R( 2); R( 3);
+               R( 4); R( 5); R( 6); R( 7);
+               R( 8); R( 9); R(10); R(11);
+               R(12); R(13); R(14); R(15);
+       }
+    /* Add the working vars back into context.state[] */
+    state[0] += a(0);
+    state[1] += b(0);
+    state[2] += c(0);
+    state[3] += d(0);
+    state[4] += e(0);
+    state[5] += f(0);
+    state[6] += g(0);
+    state[7] += h(0);
+#endif
+}
+
+/* 
+// smaller but slower
+void SHA256::Transform(word32 *state, const word32 *data)
+{
+       word32 T[20];
+       word32 W[32];
+       unsigned int i = 0, j = 0;
+       word32 *t = T+8;
+
+       memcpy(t, state, 8*4);
+       word32 e = t[4], a = t[0];
+
+       do 
+       {
+               word32 w = data[j];
+               W[j] = w;
+               w += SHA256_K[j];
+               w += t[7];
+               w += S1(e);
+               w += Ch(e, t[5], t[6]);
+               e = t[3] + w;
+               t[3] = t[3+8] = e;
+               w += S0(t[0]);
+               a = w + Maj(a, t[1], t[2]);
+               t[-1] = t[7] = a;
+               --t;
+               ++j;
+               if (j%8 == 0)
+                       t += 8;
+       } while (j<16);
+
+       do
+       {
+               i = j&0xf;
+               word32 w = s1(W[i+16-2]) + s0(W[i+16-15]) + W[i] + W[i+16-7];
+               W[i+16] = W[i] = w;
+               w += SHA256_K[j];
+               w += t[7];
+               w += S1(e);
+               w += Ch(e, t[5], t[6]);
+               e = t[3] + w;
+               t[3] = t[3+8] = e;
+               w += S0(t[0]);
+               a = w + Maj(a, t[1], t[2]);
+               t[-1] = t[7] = a;
+
+               w = s1(W[(i+1)+16-2]) + s0(W[(i+1)+16-15]) + W[(i+1)] + W[(i+1)+16-7];
+               W[(i+1)+16] = W[(i+1)] = w;
+               w += SHA256_K[j+1];
+               w += (t-1)[7];
+               w += S1(e);
+               w += Ch(e, (t-1)[5], (t-1)[6]);
+               e = (t-1)[3] + w;
+               (t-1)[3] = (t-1)[3+8] = e;
+               w += S0((t-1)[0]);
+               a = w + Maj(a, (t-1)[1], (t-1)[2]);
+               (t-1)[-1] = (t-1)[7] = a;
+
+               t-=2;
+               j+=2;
+               if (j%8 == 0)
+                       t += 8;
+       } while (j<64);
+
+    state[0] += a;
+    state[1] += t[1];
+    state[2] += t[2];
+    state[3] += t[3];
+    state[4] += e;
+    state[5] += t[5];
+    state[6] += t[6];
+    state[7] += t[7];
+}
+*/
+
+#undef S0
+#undef S1
+#undef s0
+#undef s1
+#undef R
+
+// *************************************************************
+
+void SHA384::InitState(HashWordType *state)
+{
+       static const word64 s[8] = {
+               W64LIT(0xcbbb9d5dc1059ed8), W64LIT(0x629a292a367cd507),
+               W64LIT(0x9159015a3070dd17), W64LIT(0x152fecd8f70e5939),
+               W64LIT(0x67332667ffc00b31), W64LIT(0x8eb44a8768581511),
+               W64LIT(0xdb0c2e0d64f98fa7), W64LIT(0x47b5481dbefa4fa4)};
+       memcpy(state, s, sizeof(s));
+}
+
+void SHA512::InitState(HashWordType *state)
+{
+       static const word64 s[8] = {
+               W64LIT(0x6a09e667f3bcc908), W64LIT(0xbb67ae8584caa73b),
+               W64LIT(0x3c6ef372fe94f82b), W64LIT(0xa54ff53a5f1d36f1),
+               W64LIT(0x510e527fade682d1), W64LIT(0x9b05688c2b3e6c1f),
+               W64LIT(0x1f83d9abfb41bd6b), W64LIT(0x5be0cd19137e2179)};
+       memcpy(state, s, sizeof(s));
+}
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+CRYPTOPP_ALIGN_DATA(16) static const word64 SHA512_K[80] CRYPTOPP_SECTION_ALIGN16 = {
+#else
+static const word64 SHA512_K[80] = {
+#endif
+       W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd),
+       W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc),
+       W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019),
+       W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118),
+       W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe),
+       W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2),
+       W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1),
+       W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694),
+       W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3),
+       W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65),
+       W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483),
+       W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5),
+       W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210),
+       W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4),
+       W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725),
+       W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70),
+       W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926),
+       W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df),
+       W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8),
+       W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b),
+       W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001),
+       W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30),
+       W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910),
+       W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8),
+       W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53),
+       W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8),
+       W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb),
+       W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3),
+       W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60),
+       W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec),
+       W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9),
+       W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b),
+       W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207),
+       W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178),
+       W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6),
+       W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b),
+       W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493),
+       W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c),
+       W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a),
+       W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817)
+};
+
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+// put assembly version in separate function, otherwise MSVC 2005 SP1 doesn't generate correct code for the non-assembly version
+CRYPTOPP_NAKED static void CRYPTOPP_FASTCALL SHA512_SSE2_Transform(word64 *state, const word64 *data)
+{
+#ifdef __GNUC__
+       __asm__ __volatile__
+       (
+               ".intel_syntax noprefix;"
+       AS1(    push    ebx)
+       AS2(    mov             ebx, eax)
+#else
+       AS1(    push    ebx)
+       AS1(    push    esi)
+       AS1(    push    edi)
+       AS2(    lea             ebx, SHA512_K)
+#endif
+
+       AS2(    mov             eax, esp)
+       AS2(    and             esp, 0xfffffff0)
+       AS2(    sub             esp, 27*16)                             // 17*16 for expanded data, 20*8 for state
+       AS1(    push    eax)
+       AS2(    xor             eax, eax)
+       AS2(    lea             edi, [esp+4+8*8])               // start at middle of state buffer. will decrement pointer each round to avoid copying
+       AS2(    lea             esi, [esp+4+20*8+8])    // 16-byte alignment, then add 8
+
+       AS2(    movdqa  xmm0, [ecx+0*16])
+       AS2(    movdq2q mm4, xmm0)
+       AS2(    movdqa  [edi+0*16], xmm0)
+       AS2(    movdqa  xmm0, [ecx+1*16])
+       AS2(    movdqa  [edi+1*16], xmm0)
+       AS2(    movdqa  xmm0, [ecx+2*16])
+       AS2(    movdq2q mm5, xmm0)
+       AS2(    movdqa  [edi+2*16], xmm0)
+       AS2(    movdqa  xmm0, [ecx+3*16])
+       AS2(    movdqa  [edi+3*16], xmm0)
+       ASJ(    jmp,    0, f)
+
+#define SSE2_S0_S1(r, a, b, c) \
+       AS2(    movq    mm6, r)\
+       AS2(    psrlq   r, a)\
+       AS2(    movq    mm7, r)\
+       AS2(    psllq   mm6, 64-c)\
+       AS2(    pxor    mm7, mm6)\
+       AS2(    psrlq   r, b-a)\
+       AS2(    pxor    mm7, r)\
+       AS2(    psllq   mm6, c-b)\
+       AS2(    pxor    mm7, mm6)\
+       AS2(    psrlq   r, c-b)\
+       AS2(    pxor    r, mm7)\
+       AS2(    psllq   mm6, b-a)\
+       AS2(    pxor    r, mm6)
+
+#define SSE2_s0(r, a, b, c)    \
+       AS2(    movdqa  xmm6, r)\
+       AS2(    psrlq   r, a)\
+       AS2(    movdqa  xmm7, r)\
+       AS2(    psllq   xmm6, 64-c)\
+       AS2(    pxor    xmm7, xmm6)\
+       AS2(    psrlq   r, b-a)\
+       AS2(    pxor    xmm7, r)\
+       AS2(    psrlq   r, c-b)\
+       AS2(    pxor    r, xmm7)\
+       AS2(    psllq   xmm6, c-a)\
+       AS2(    pxor    r, xmm6)
+
+#define SSE2_s1(r, a, b, c)    \
+       AS2(    movdqa  xmm6, r)\
+       AS2(    psrlq   r, a)\
+       AS2(    movdqa  xmm7, r)\
+       AS2(    psllq   xmm6, 64-c)\
+       AS2(    pxor    xmm7, xmm6)\
+       AS2(    psrlq   r, b-a)\
+       AS2(    pxor    xmm7, r)\
+       AS2(    psllq   xmm6, c-b)\
+       AS2(    pxor    xmm7, xmm6)\
+       AS2(    psrlq   r, c-b)\
+       AS2(    pxor    r, xmm7)
+
+       ASL(SHA512_Round)
+       // k + w is in mm0, a is in mm4, e is in mm5
+       AS2(    paddq   mm0, [edi+7*8])         // h
+       AS2(    movq    mm2, [edi+5*8])         // f
+       AS2(    movq    mm3, [edi+6*8])         // g
+       AS2(    pxor    mm2, mm3)
+       AS2(    pand    mm2, mm5)
+       SSE2_S0_S1(mm5,14,18,41)
+       AS2(    pxor    mm2, mm3)
+       AS2(    paddq   mm0, mm2)                       // h += Ch(e,f,g)
+       AS2(    paddq   mm5, mm0)                       // h += S1(e)
+       AS2(    movq    mm2, [edi+1*8])         // b
+       AS2(    movq    mm1, mm2)
+       AS2(    por             mm2, mm4)
+       AS2(    pand    mm2, [edi+2*8])         // c
+       AS2(    pand    mm1, mm4)
+       AS2(    por             mm1, mm2)
+       AS2(    paddq   mm1, mm5)                       // temp = h + Maj(a,b,c)
+       AS2(    paddq   mm5, [edi+3*8])         // e = d + h
+       AS2(    movq    [edi+3*8], mm5)
+       AS2(    movq    [edi+11*8], mm5)
+       SSE2_S0_S1(mm4,28,34,39)                        // S0(a)
+       AS2(    paddq   mm4, mm1)                       // a = temp + S0(a)
+       AS2(    movq    [edi-8], mm4)
+       AS2(    movq    [edi+7*8], mm4)
+       AS1(    ret)
+
+       // first 16 rounds
+       ASL(0)
+       AS2(    movq    mm0, [edx+eax*8])
+       AS2(    movq    [esi+eax*8], mm0)
+       AS2(    movq    [esi+eax*8+16*8], mm0)
+       AS2(    paddq   mm0, [ebx+eax*8])
+       ASC(    call,   SHA512_Round)
+       AS1(    inc             eax)
+       AS2(    sub             edi, 8)
+       AS2(    test    eax, 7)
+       ASJ(    jnz,    0, b)
+       AS2(    add             edi, 8*8)
+       AS2(    cmp             eax, 16)
+       ASJ(    jne,    0, b)
+
+       // rest of the rounds
+       AS2(    movdqu  xmm0, [esi+(16-2)*8])
+       ASL(1)
+       // data expansion, W[i-2] already in xmm0
+       AS2(    movdqu  xmm3, [esi])
+       AS2(    paddq   xmm3, [esi+(16-7)*8])
+       AS2(    movdqa  xmm2, [esi+(16-15)*8])
+       SSE2_s1(xmm0, 6, 19, 61)
+       AS2(    paddq   xmm0, xmm3)
+       SSE2_s0(xmm2, 1, 7, 8)
+       AS2(    paddq   xmm0, xmm2)
+       AS2(    movdq2q mm0, xmm0)
+       AS2(    movhlps xmm1, xmm0)
+       AS2(    paddq   mm0, [ebx+eax*8])
+       AS2(    movlps  [esi], xmm0)
+       AS2(    movlps  [esi+8], xmm1)
+       AS2(    movlps  [esi+8*16], xmm0)
+       AS2(    movlps  [esi+8*17], xmm1)
+       // 2 rounds
+       ASC(    call,   SHA512_Round)
+       AS2(    sub             edi, 8)
+       AS2(    movdq2q mm0, xmm1)
+       AS2(    paddq   mm0, [ebx+eax*8+8])
+       ASC(    call,   SHA512_Round)
+       // update indices and loop
+       AS2(    add             esi, 16)
+       AS2(    add             eax, 2)
+       AS2(    sub             edi, 8)
+       AS2(    test    eax, 7)
+       ASJ(    jnz,    1, b)
+       // do housekeeping every 8 rounds
+       AS2(    mov             esi, 0xf)
+       AS2(    and             esi, eax)
+       AS2(    lea             esi, [esp+4+20*8+8+esi*8])
+       AS2(    add             edi, 8*8)
+       AS2(    cmp             eax, 80)
+       ASJ(    jne,    1, b)
+
+#define SSE2_CombineState(i)   \
+       AS2(    movdqa  xmm0, [edi+i*16])\
+       AS2(    paddq   xmm0, [ecx+i*16])\
+       AS2(    movdqa  [ecx+i*16], xmm0)
+
+       SSE2_CombineState(0)
+       SSE2_CombineState(1)
+       SSE2_CombineState(2)
+       SSE2_CombineState(3)
+
+       AS1(    pop             esp)
+       AS1(    emms)
+
+#if defined(__GNUC__)
+       AS1(    pop             ebx)
+       ".att_syntax prefix;"
+               :
+               : "a" (SHA512_K), "c" (state), "d" (data)
+               : "%esi", "%edi", "memory", "cc"
+       );
+#else
+       AS1(    pop             edi)
+       AS1(    pop             esi)
+       AS1(    pop             ebx)
+       AS1(    ret)
+#endif
+}
+#endif // #if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE
+
+void SHA512::Transform(word64 *state, const word64 *data)
+{
+#if CRYPTOPP_BOOL_SSE2_ASM_AVAILABLE && CRYPTOPP_BOOL_X86
+       if (HasSSE2())
+       {
+               SHA512_SSE2_Transform(state, data);
+               return;
+       }
+#endif
+
+#define S0(x) (rotrFixed(x,28)^rotrFixed(x,34)^rotrFixed(x,39))
+#define S1(x) (rotrFixed(x,14)^rotrFixed(x,18)^rotrFixed(x,41))
+#define s0(x) (rotrFixed(x,1)^rotrFixed(x,8)^(x>>7))
+#define s1(x) (rotrFixed(x,19)^rotrFixed(x,61)^(x>>6))
+
+#define R(i) h(i)+=S1(e(i))+Ch(e(i),f(i),g(i))+SHA512_K[i+j]+(j?blk2(i):blk0(i));\
+       d(i)+=h(i);h(i)+=S0(a(i))+Maj(a(i),b(i),c(i))
+
+       word64 W[16];
+       word64 T[8];
+    /* Copy context->state[] to working vars */
+       memcpy(T, state, sizeof(T));
+    /* 80 operations, partially loop unrolled */
+       for (unsigned int j=0; j<80; j+=16)
+       {
+               R( 0); R( 1); R( 2); R( 3);
+               R( 4); R( 5); R( 6); R( 7);
+               R( 8); R( 9); R(10); R(11);
+               R(12); R(13); R(14); R(15);
+       }
+    /* Add the working vars back into context.state[] */
+    state[0] += a(0);
+    state[1] += b(0);
+    state[2] += c(0);
+    state[3] += d(0);
+    state[4] += e(0);
+    state[5] += f(0);
+    state[6] += g(0);
+    state[7] += h(0);
+}
+
+NAMESPACE_END
+
+#endif // #ifndef CRYPTOPP_GENERATE_X64_MASM
+#endif // #ifndef CRYPTOPP_IMPORTS
index 8b57a24..d1a06f7 100644 (file)
@@ -11,7 +11,7 @@ class BitcoinAddressValidator : public QRegExpValidator
 public:
     explicit BitcoinAddressValidator(QObject *parent = 0);
 
-    static const QString valid_chars;
+    static const int MaxAddressLength = 34;
 signals:
 
 public slots:
index 408027b..8e71916 100644 (file)
@@ -1,8 +1,8 @@
 #include "bitcoinaddressvalidator.h"
 
-const QString BitcoinAddressValidator::valid_chars = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ";
+#include "base58.h"
 
 BitcoinAddressValidator::BitcoinAddressValidator(QObject *parent) :
-    QRegExpValidator(QRegExp("^["+valid_chars+"]+"), parent)
+    QRegExpValidator(QRegExp(QString("^[")+QString(pszBase58)+QString("]+")), parent)
 {
 }
index 6f459fb..6c216d3 100644 (file)
@@ -12,6 +12,7 @@ SendCoinsDialog::SendCoinsDialog(QWidget *parent) :
     ui(new Ui::SendCoinsDialog)
 {
     ui->setupUi(this);
+    ui->payTo->setMaxLength(BitcoinAddressValidator::MaxAddressLength);
     ui->payTo->setValidator(new BitcoinAddressValidator(this));
     ui->payAmount->setValidator(new QDoubleValidator(this));
 }
index e353532..c207af1 100644 (file)
@@ -311,7 +311,7 @@ public:
         CAutoBN_CTX pctx;
         CBigNum bnBase = nBase;
         CBigNum bn0 = 0;
-        string str;
+        std::string str;
         CBigNum bn = *this;
         BN_set_negative(&bn, false);
         CBigNum dv;
@@ -351,7 +351,7 @@ public:
     template<typename Stream>
     void Unserialize(Stream& s, int nType=0, int nVersion=VERSION)
     {
-        vector<unsigned char> vch;
+        std::vector<unsigned char> vch;
         ::Unserialize(s, vch, nType, nVersion);
         setvch(vch);
     }
index 356b2dc..14feb16 100644 (file)
@@ -302,7 +302,7 @@ public:
         char psz[sizeof(pn)*2 + 1];
         for (int i = 0; i < sizeof(pn); i++)
             sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]);
-        return string(psz, psz + sizeof(pn)*2);
+        return std::string(psz, psz + sizeof(pn)*2);
     }
 
     void SetHex(const char* psz)
@@ -632,7 +632,7 @@ inline const uint256 operator-(const uint256& a, const uint256& b)      { return
 
 
 
-inline int Testuint256AdHoc(vector<string> vArg)
+inline int Testuint256AdHoc(std::vector<std::string> vArg)
 {
     uint256 g(0);
 
index af8cfcf..e25004f 100644 (file)
@@ -5,8 +5,11 @@
 #define BITCOIN_UTIL_H
 
 #include "uint256.h"
+//#include "cryptopp/sha.h"
 
 #include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 #include <map>
 #include <vector>
 #include <string>
@@ -16,6 +19,9 @@
 #include <boost/date_time/gregorian/gregorian_types.hpp>
 #include <boost/date_time/posix_time/posix_time_types.hpp>
 
+#include <openssl/sha.h>
+#include <openssl/ripemd.h>
+
 
 #if defined(_MSC_VER) || defined(__BORLANDC__)
 typedef __int64  int64;
@@ -552,7 +558,7 @@ uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=VERSION)
     return Hash(ss.begin(), ss.end());
 }
 
-inline uint160 Hash160(const vector<unsigned char>& vch)
+inline uint160 Hash160(const std::vector<unsigned char>& vch)
 {
     uint256 hash1;
     SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);