diff --git a/Builds/VisualStudio2012/beast.vcxproj b/Builds/VisualStudio2012/beast.vcxproj
index f55e325993..f0916e7e26 100644
--- a/Builds/VisualStudio2012/beast.vcxproj
+++ b/Builds/VisualStudio2012/beast.vcxproj
@@ -21,6 +21,8 @@
+
+
@@ -87,7 +89,11 @@
+
+
+
+
@@ -95,6 +101,7 @@
+
@@ -384,6 +391,31 @@
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+ true
+
true
diff --git a/Builds/VisualStudio2012/beast.vcxproj.filters b/Builds/VisualStudio2012/beast.vcxproj.filters
index b0278d174b..7afce30be6 100644
--- a/Builds/VisualStudio2012/beast.vcxproj.filters
+++ b/Builds/VisualStudio2012/beast.vcxproj.filters
@@ -67,6 +67,12 @@
beast_core
+
+ beast\crypto\impl\sha2
+
+
+ beast\crypto\impl\sha2
+
@@ -249,6 +255,15 @@
{1fff3bd8-44ae-41df-8dd4-8bb6f07b2908}
+
+ {9c1ef4c4-5623-4500-859f-12d6ce5ae362}
+
+
+ {fc3d3f14-9ba1-43e4-b086-cbbd2f63b944}
+
+
+ {44489531-f44a-439a-a6ea-d32c252b1e8b}
+
@@ -530,7 +545,6 @@
beast_core\zip\zlib
-
beast_core\memory
@@ -1161,6 +1175,22 @@
beast\http
+
+
+ beast
+
+
+ beast\intrusive
+
+
+ beast
+
+
+ beast\crypto\impl\sha2
+
+
+ beast\crypto
+
@@ -1712,6 +1742,21 @@
beast\http\impl
+
+ beast\crypto\impl\sha2
+
+
+ beast\crypto\impl\sha2
+
+
+ beast\crypto\impl\sha2
+
+
+ beast\crypto
+
+
+ beast\crypto\impl
+
diff --git a/beast/Crypto.h b/beast/Crypto.h
new file mode 100644
index 0000000000..a5f9f6d12a
--- /dev/null
+++ b/beast/Crypto.h
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_CRYPTO_H_INCLUDED
+#define BEAST_CRYPTO_H_INCLUDED
+
+#include "crypto/api/Sha256.h"
+
+#endif
+
diff --git a/beast/FixedArray.h b/beast/FixedArray.h
new file mode 100644
index 0000000000..e9d50488af
--- /dev/null
+++ b/beast/FixedArray.h
@@ -0,0 +1,165 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_FIXEDARRAY_H_INCLUDED
+#define BEAST_FIXEDARRAY_H_INCLUDED
+
+#include "Config.h"
+
+#include
+#include
+#include
+
+namespace beast {
+
+// Ideas from Boost
+
+/** An array whose size is determined at compile-time.
+ The interface tries to follow std::vector as closely as possible within
+ the limitations of having a fixed size.
+*/
+template
+class FixedArray
+{
+public:
+ T values [N];
+
+ typedef T value_type;
+ typedef T* iterator;
+ typedef T const* const_iterator;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ // iterators
+ iterator begin() { return values; }
+ const_iterator begin() const { return values; }
+ const_iterator cbegin() const { return values; }
+ iterator end() { return values+N; }
+ const_iterator end() const { return values+N; }
+ const_iterator cend() const { return values+N; }
+
+ typedef std::reverse_iterator reverse_iterator;
+ typedef std::reverse_iterator const_reverse_iterator;
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
+
+ reference operator[](size_type i)
+ {
+ bassert (i < N);
+ return values[i];
+ }
+
+ const_reference operator[](size_type i) const
+ {
+ bassert (i < N);
+ return values[i];
+ }
+
+ reference at(size_type i) { rangecheck(i); return values[i]; }
+ const_reference at(size_type i) const { rangecheck(i); return values[i]; }
+
+ reference front() { return values[0]; }
+ reference back() { return values[N-1]; }
+ const_reference front () const { return values[0]; }
+ const_reference back() const { return values[N-1]; }
+
+ static size_type size() { return N; }
+ static bool empty() { return false; }
+ static size_type max_size() { return N; }
+
+ enum { static_size = N };
+
+ T const* data() const { return values; }
+ T* data() { return values; }
+ T* c_array() { return values; }
+
+ template
+ FixedArray& operator= (FixedArray const& rhs)
+ {
+ std::copy (rhs.begin(), rhs.end(), begin());
+ return *this;
+ }
+
+ void assign (T const& value) { fill (value); }
+
+ void fill (T const& value)
+ {
+ std::fill_n (begin(), size(), value);
+ }
+
+ void clear ()
+ {
+ fill (T ());
+ }
+
+ static void rangecheck (size_type i)
+ {
+ if (i >= size())
+ throw std::out_of_range ("FixedArray<>: index out of range");
+ }
+};
+
+//------------------------------------------------------------------------------
+
+template
+bool operator== (FixedArray const& lhs, FixedArray const& rhs)
+{
+ return std::equal (lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template
+bool operator!= (FixedArray const& lhs, FixedArray const& rhs)
+{
+ return !(lhs==rhs);
+}
+
+template
+bool operator< (FixedArray const& lhs, FixedArray const& rhs)
+{
+ return std::lexicographical_compare (lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
+
+template
+bool operator> (FixedArray const& lhs, FixedArray const& rhs)
+{
+ return rhs
+bool operator<= (FixedArray const& lhs, FixedArray const& rhs)
+{
+ return !(rhs
+bool operator>= (FixedArray const& lhs, FixedArray const& rhs)
+{
+ return !(lhs
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "BeastConfig.h"
+
+#include "../CStdInt.h"
+#include "../config/PlatformConfig.h"
+
+#include "impl/Sha256.cpp"
diff --git a/beast/crypto/Sha256.h b/beast/crypto/Sha256.h
new file mode 100644
index 0000000000..95865d8b34
--- /dev/null
+++ b/beast/crypto/Sha256.h
@@ -0,0 +1,156 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_CRYPTO_Sha256_H_INCLUDED
+#define BEAST_CRYPTO_Sha256_H_INCLUDED
+
+#include "../config/PlatformConfig.h"
+#include "../CStdInt.h"
+#include "../FixedArray.h"
+
+//------------------------------------------------------------------------------
+
+namespace beast {
+namespace Sha256 {
+
+enum
+{
+ digestLength = 32,
+ blockLength = 64
+};
+
+/** A container suitable for holding the resulting hash. */
+typedef FixedArray digest_type;
+
+namespace detail {
+struct Context
+{
+ beast::uint32 state[8];
+ beast::uint64 bitcount;
+ beast::uint8 buffer[Sha256::blockLength];
+};
+}
+
+/** Computes the Sha256 hash of data. */
+class Context
+{
+public:
+ /** Create a new hasher prepared for input. */
+ Context();
+
+ /** Update the hashing context with the input sequence. */
+ /** @{ */
+ void update (void const* buffer, std::size_t bytes);
+
+ void update (int8 const* begin, int8 const* end)
+ {
+ update (begin, end - begin);
+ }
+
+ void update (uint8 const* begin, uint8 const* end)
+ {
+ update (begin, end - begin);
+ }
+
+ template
+ void update (T const& t)
+ {
+ update (&t, sizeof(T));
+ }
+ /** @} */
+
+ /** Finalize the hash process and store the digest.
+ The memory pointed to by `digest` must be at least digestLength
+ bytes. This object may not be re-used after calling finish.
+ @return A pointer to the passed hash buffer.
+ */
+ /** @{ */
+ void* finish (void* digest);
+
+ digest_type& finish (digest_type& digest)
+ {
+ finish (digest.c_array());
+ return digest;
+ }
+
+ digest_type finish ()
+ {
+ digest_type digest;
+ finish (digest);
+ return digest;
+ }
+ /** @} */
+
+private:
+ detail::Context m_context;
+};
+
+//------------------------------------------------------------------------------
+
+/** Returns the hash produced by a single octet equal to zero. */
+digest_type const& empty_digest();
+
+/** Performs an entire hashing operation in a single step.
+ A zero length input sequence produces the empty_digest().
+ @return The resulting digest depending on the arguments.
+*/
+/** @{ */
+void* hash (void const* buffer, std::size_t bytes, void* digest);
+digest_type& hash ( void const* buffer, std::size_t bytes, digest_type& digest);
+digest_type hash (void const* buffer, std::size_t bytes);
+void* hash (int8 const* begin, int8 const* end, void* digest);
+void* hash (uint8 const* begin, uint8 const* end, void* digest);
+digest_type hash (int8 const* begin, int8 const* end);
+digest_type hash (uint8 const* begin, uint8 const* end);
+
+template
+void* hash (T const& t, void* digest)
+{
+ return hash (&t, sizeof(T), digest);
+}
+
+template
+digest_type& hash (T const& t, digest_type& digest)
+{
+ return hash (&t, sizeof(T), digest);
+}
+
+template
+digest_type hash (T const& t)
+{
+ digest_type digest;
+ hash (&t, sizeof(T), digest);
+ return digest;
+}
+/** @} */
+
+/** Calculate the hash of a hash in one step.
+ The memory pointed to by source_digest must be at
+ least digestLength bytes or undefined behavior results.
+*/
+/** @{ */
+void* hash (void const* source_digest, void* digest);
+digest_type& hash (void const* source_digest, digest_type& digest);
+digest_type hash (void const* source_digest);;
+/** @} */
+
+}
+}
+
+#endif
diff --git a/beast/crypto/impl/Sha256.cpp b/beast/crypto/impl/Sha256.cpp
new file mode 100644
index 0000000000..261508ea92
--- /dev/null
+++ b/beast/crypto/impl/Sha256.cpp
@@ -0,0 +1,147 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#include "../Sha256.h"
+
+namespace beast {
+namespace Sha256 {
+
+#ifndef LITTLE_ENDIAN
+# define LITTLE_ENDIAN 1234
+#endif
+#ifndef BIG_ENDIAN
+# define BIG_ENDIAN 4321
+#endif
+#if !defined(BYTE_ORDER)
+# if BEAST_BIG_ENDIAN
+# define BYTE_ORDER BIG_ENDIAN
+# else
+# define BYTE_ORDER LITTLE_ENDIAN
+# endif
+#endif
+
+//#define SHA2_USE_INTTYPES_H
+
+namespace detail {
+typedef uint8 u_int8_t;
+typedef uint32 u_int32_t;
+typedef uint64 u_int64_t;
+#include "sha2/sha2.c"
+}
+
+Context::Context ()
+{
+ detail::SHA256_Init (&m_context);
+}
+
+void Context::update (void const* buffer, std::size_t bytes)
+{
+ detail::SHA256_Update (&m_context, static_cast (buffer), bytes);
+}
+
+void* Context::finish (void* hash)
+{
+ detail::SHA256_Final (static_cast (hash), &m_context);
+ return hash;
+}
+
+//------------------------------------------------------------------------------
+
+digest_type const& empty_digest()
+{
+ struct Holder
+ {
+ Holder ()
+ {
+ uint8 zero (0);
+ hash (zero, digest);
+ }
+
+ digest_type digest;
+ };
+
+ static Holder const holder;
+
+ return holder.digest;
+}
+
+void* hash (void const* buffer, std::size_t bytes, void* digest)
+{
+ Context h;
+ h.update (buffer, bytes);
+ h.finish (digest);
+ return digest;
+}
+
+digest_type& hash (void const* buffer, std::size_t bytes, digest_type& digest)
+{
+ hash (buffer, bytes, digest.c_array());
+ return digest;
+}
+
+digest_type hash (void const* buffer, std::size_t bytes)
+{
+ digest_type digest;
+ hash (buffer, bytes, digest);
+ return digest;
+}
+
+void* hash (int8 const* begin, int8 const* end, void* digest)
+{
+ return hash (begin, end - begin, digest);
+}
+
+void* hash (uint8 const* begin, uint8 const* end, void* digest)
+{
+ return hash (begin, end - begin, digest);
+}
+
+digest_type hash (int8 const* begin, int8 const* end)
+{
+ digest_type digest;
+ hash (begin, end - begin, digest);
+ return digest;
+}
+
+digest_type hash (uint8 const* begin, uint8 const* end)
+{
+ digest_type digest;
+ hash (begin, end - begin, digest);
+ return digest;
+}
+
+void* hash (void const* source_digest, void* digest)
+{
+ return hash (source_digest, digestLength, digest);
+}
+
+digest_type& hash (void const* source_digest, digest_type& digest)
+{
+ return hash (source_digest, digestLength, digest);
+}
+
+digest_type hash (void const* source_digest)
+{
+ digest_type digest;
+ hash (source_digest, digestLength, digest);
+ return digest;
+}
+
+}
+}
diff --git a/beast/crypto/impl/sha2/README b/beast/crypto/impl/sha2/README
new file mode 100644
index 0000000000..a1b684d1e0
--- /dev/null
+++ b/beast/crypto/impl/sha2/README
@@ -0,0 +1,277 @@
+VERSION:
+
+This is version 1.0.1 RELEASE
+
+While this is my "release" version, due to lack of additional
+official test vectors against which to verify this implementation's
+correctness, beware that there may be implementation bugs. Also,
+it has not yet been tested on very many other architectures,
+big-endian machines in particular.
+
+
+LICENSE:
+
+This implementation is released freely under an open-source BSD
+license which appears at the top of each source code file.
+
+
+WHAT IT IS:
+
+The files sha2.h and sha2.c implement the SHA-256, SHA-384, and SHA-512
+hash algorithms as described in the PDF document found at the following
+web address:
+
+ http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
+
+The interface is similar to the interface to SHA-1 found in the OpenSSL
+library.
+
+The file sha2prog.c is a simple program that accepts input from either
+STDIN or reads one or more files specified on the command line, and then
+generates the specified hash (either SHA-256, SHA-384, SHA-512, or any
+combination thereof, including all three at once).
+
+
+LIMITATIONS:
+
+This implementation has several limitations:
+
+ * Input data is only accepted in octet-length increments. No sub-byte
+ data is handled. The NIST document describes how to handle sub-byte
+ input data, but for ease of implementation this version will only
+ accept message data in multiples of bytes.
+ * This implementation utilizes 64-bit integer data types. If your
+ system and compiler does not have a 64-bit integer data type, this
+ implementation will not work.
+ * Because of the use of 64-bit operations, many 32-bit architectures
+ that do have 64-bit data types but do operations most efficiently
+ on 32-bit words, this implementation may be slower than an
+ implementation designed to use only 32-bit words (emulating the
+ 64-bit operations).
+ * On platforms with 128-bit integer data types, the SHA-384 and SHA-512
+ bit counters used by this implementation might be better off using
+ the 128-bit type instead of simulating it with two 64-bit integers.
+ * This implementation was written in C in hopes of portability and for
+ the fun of it during my spare time. It is probably not the most
+ efficient or fastest C implementation. I welcome suggestions,
+ however, that suggest ways to speed things up without breaking
+ portability. I also welcome suggestions to improve portability.
+ * As mentioned above, this code has NOT been thoroughly tested.
+ This is perhaps the most severe limitation.
+
+
+BEFORE YOU COMPILE (OPTIONS):
+
+Each of the options described below may either be defined in the sha2.h
+header file (or in the sha2.c file in some cases), or on the command
+line at compile time if your compiler supports such things. For
+example:
+
+ #define SHA2_USE_INTTYPES_H
+ #define SHA2_UNROLL_TRANSFORM
+
+Or:
+
+ cc -c -DSHA2_UNROLL_TRANSFORM sha2.c
+ cc -c -DBYTE_ORDER=4321 -DBIG_ENDIAN=4321 sha2.c
+
+Here are the available options. Read on below for a description of
+each one:
+
+ SHA2_USE_INTTYPES_H
+ SHA2_USE_MEMSET_MEMCPY/SHA2_USE_BZERO_BCOPY
+ SHA2_UNROLL_TRANSFORM
+ BYTE_ORDER (LITTLE_ENDIAN/BIG_ENDIAN)
+
+* SHA2_USE_INTTYPES_H option:
+By default, this code uses u_intXX_t data types for 8 bit, 32 bit, and
+64 bit unsigned integer type definitions. Most BSD systems define these,
+as does Linux. However, some (like Compaq's Tru64 Unix) may instead
+use uintXX_t data types as defined by recent ANSI C standards and as
+included in the inttypes.h header file. Those wanting to use inttypes.h
+need to define this either in sha.h or at compile time.
+
+On those systems where NEITHER definitions are available, you will need
+to edit both sha2.h and sha2.c and define things by hand in the appropriate
+sections.
+
+* BYTE_ORDER definitions:
+This code assumes that BYTE_ORDER will be defined by the system during
+compile to either equal LITTLE_ENDIAN or BIG_ENDIAN. If your system
+does not define these, you may need to define them by hand in the sha.c
+file according to the byte ordering conventions of your system.
+
+* SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY
+The code in sha2.c can use either memset()/memcpy() for memory block
+operations, or bzero()/mcopy(). If you define neither of these, the
+code will default to memset()/memcpy(). You can define either at the
+command line or in sha2.h or in sha2.c.
+
+* SHA2_UNROLL_TRANSFORM
+By defining this either on the command line or in sha2.h or sha2.c,
+the code will use macros to partially "unroll" the SHA transform
+function. This usually generates bigger executables. It CAN (but
+not necessarily WILL) generate faster code when you tell your compiler
+to optimize things. For example, on the FreeBSD and Linux x86 systems
+I tested things on (using gcc), when I optimized with just -O2 and
+unrolled the transform, the hash transform was faster by 15-30%. On
+these same systems, if I did NO optimization, the unrolled transform
+was SLOWER, much slower (I'm guessing because the code was breaking
+the cache, but I'm not sure). Your mileage may vary.
+
+
+PORTABILITY:
+
+The code in sha2.c and sha2.h is intended to be portable. It may
+require that you do a few #definitions in the .h file. I've successfully
+compiled and tested the sha2.c and sha2.h code on Apple's OS X (on
+a PPC), FreeBSD 4.1.1 on Intel, Linux on Intel, FreeBSD on the Alpha,
+and even under Windows98SE using Metrowerks C. The utility/example
+programs (sha2prog.c, sha2test.c, and sha2speed.c) will very likely
+have more trouble in portability since they do I/O.
+
+To get sha2.c/sha2.h working under Windows, I had to define
+SHA2_USE_INTTYPES_H, BYTE_ORDER, LITTLE_ENDIAN, and had to comment
+out the include of in sha2.h. With a bit more work
+I got the test program to run and verified that all the test
+cases passed.
+
+
+SUGGESTIONS/BUG FIXES:
+
+If you make changes to get it working on other architectures, if you fix
+any bugs, or if you make changes that improve this implementation's
+efficiency that would be relatively portable and you're willing to release
+your changes under the same license, please send them to me for possible
+inclusion in future versions.
+
+If you know where I can find some additional test vectors, please let me
+know.
+
+
+CHANGE HISTORY:
+
+0.8 to 0.9 - Fixed spelling errors, changed to u_intXX_t type usage,
+ removed names from prototypes, added prototypes to sha2.c,
+ and a few things I can't recall.
+
+0.9 to 0.9.5 - Add a new define in sha2.c that permits one to compile
+ it to either use memcpy()/memset() or bcopy()/bzero()
+ for memory block copying and zeroing. Added support
+ for unrolled SHA-256/384/512 transform loops. Just
+ compile with SHA2_UNROLL_TRANSFORM to enable. It takes
+ longer to compile, but I hope it is a bit faster. I
+ need to do some test to see whether or not it is. Oh,
+ in sha2.c, you either need to define SHA2_USE_BZERO_BCOPY
+ or SHA2_USE_MEMSET_MEMCPY to choose which way you want
+ to compile. *Whew* It's amazing how quickly something
+ simple starts to grow more complex even in the span of
+ just a few hours. I didn't really intend to do this much.
+0.9.5 to 0.9.6 - Added a test program (sha2test) which tests against several
+ known test vectors. WARNING: Some of the test output
+ hashes are NOT from NIST's documentation and are the
+ output of this implementation and so may be incorrect.
+0.9.6 to 0.9.7 - Fixed a bug that could cause invalid output in certain
+ cases and added an assumed scenario where zero-length
+ data is hashed. Also changed the rotation macros to use
+ a temporary variable as this reduces the number of operations.
+ When data is fed in blocks of the right length, copying of
+ data is reduced in this version. Added SHAYXZ_Data()
+ functions for ease of hashing a set of data. Added another
+ file sha2speed.c for doing speed testing. Added another test
+ vector with a larger data size (16KB). Fixed u_intXX_t and
+ uintXX_t handling by adding a define for SHA2_USE_INTTYPES_H
+ as well as made a few other minor changes to get rid of
+ warnings when compiling on Compaq's Tru64 Unix.
+0.9.7 to 0.9.8 - The bug fix in 0.9.7 was incomplete and in some cases made
+ things worse. I believe that 0.9.8 fixes the bug completely
+ so that output is correct. I cannot verify this, however,
+ because of the lack of test vectors against which to do such
+ verification. All versions correctly matched the very few
+ NIST-provided vectors, but unfortunately the bug only
+ appeared in longer message data sets.
+0.9.8 to 0.9.9 - Fixed some really bad typos and mistakes on my part that
+ only affected big-endian systems. I didn't have direct
+ access for testing before this version. Thanks to
+ Lucas Marshall for giving me access to his OS X system.
+0.9.9 to 1.0.0b1 Added a few more test samples and made a few changes to
+ make things easier compiling on several other platforms.
+ Also I experimented with alternate macro definitions
+ in the SHA2_UNROLL_TRANSFORM version (see sha2.slower.c)
+ and eliminated the T1 temporary variable (the compiler
+ would of course still use internal temporary storage
+ during expression evaluation, but I'd hoped the compiler
+ would be more efficient), but unfortunately under FreeBSD
+ 4.1.1-STABLE on an x86 platform, the change slowed things
+ down.
+1.0.0b1 to 1.0 RELEASE Fixed an off-by-one implementation bug that affected
+ SHA-256 when hashed data length L = 55 + 64 * X where X is
+ either zero or a positive integer, and another (basically
+ the same bug) bug in SHA-384 and SHA-512 that showed up when
+ hashed data lengths L = 111 + 128 * X. Thanks to Rogier
+ van de Pol for sending me test data that revealed the bug.
+ The fix was very simple (just two tiny changes). Also,
+ I finally put the files into RCS so future changes will be
+ easier to manage. The sha2prog.c file was rewritten to
+ be more useful to me, and I got rid of the old C testing
+ program and now use a perl script with a subdirectory full
+ of test data. It's a more flexible test system.
+
+1.0 to 1.0.1 - Specified the specific *_CTX structure in the MEMSET_BZERO
+ macro doing clean-up after hashing. This should eliminate
+ some warnings using Clang in version 3.0 (trunk 135348).
+ Thanks, Stephane Leon for reporting this.
+
+
+LATEST VERSION:
+
+The latest version and documentation (if any ;) should always be available
+on the web at:
+
+ http://www.aarongifford.com/computers/sha.html
+
+
+CONTACT ME:
+
+I can be reached via email at:
+
+ Aaron Gifford
+
+Please don't send support questions. I don't have the time to answer and
+they'll probably be ignored. Bug fixes, or patches that add something useful
+will be gratefully accepted, however.
+
+If you use this implementation, I would enjoy getting a brief email message
+letting me know who you are and what use to which it is being put. There
+is no requirement to do so. I just think it would be fun.
+
+
+EXAMPLES:
+
+Here's an example of compiling and using the sha2 program (in this example
+I build it using the unrolled transform version with -O2 optimizations),
+and then running the perl testing script:
+
+ cc -O2 -DSHA2_UNROLL_TRANSFORM -Wall -o sha2 sha2prog.c sha2.c
+ % ./sha2test.pl
+
+ [most of the perl script output deleted for brevity]
+
+ ===== RESULTS (18 VECTOR DATA FILES HASHED) =====
+
+ HASH TYPE NO. OF TESTS PASSED FAILED
+ --------- ------------ ------ ------
+ SHA-256 18 18 0
+ SHA-384 18 18 0
+ SHA-512 18 18 0
+ ----------------------------------------------
+ TOTAL: 54 54 0
+
+ NO ERRORS! ALL TESTS WERE SUCCESSFUL!
+
+ ALL TEST VECTORS PASSED!
+
+That's all folks! Have fun!
+
+Aaron out.
+
diff --git a/beast/crypto/impl/sha2/sha2.c b/beast/crypto/impl/sha2/sha2.c
new file mode 100644
index 0000000000..ab71a26644
--- /dev/null
+++ b/beast/crypto/impl/sha2/sha2.c
@@ -0,0 +1,1052 @@
+/*
+ * FILE: sha2.c
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include /* memcpy()/memset() or bcopy()/bzero() */
+#include /* assert() */
+#include "sha2.h"
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert(). On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined. Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file). Either define on the command line, for example:
+ *
+ * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ * #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER. If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ * #define LITTLE_ENDIAN 1234
+ * #define BIG_ENDIAN 4321
+ *
+ * And for little-endian machines, add:
+ *
+ * #define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ * #define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including (which in turn includes
+ * where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+/*
+ * Define the followingsha2_* types to types of the correct length on
+ * the native archtecture. Most BSD systems and Linux define u_intXX_t
+ * types. Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+
+typedef u_int8_t sha2_byte; /* Exactly 1 byte */
+typedef u_int32_t sha2_word32; /* Exactly 4 bytes */
+typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define SHA256_SHORT_BLOCK_LENGTH (Sha256::blockLength - 8)
+#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x) { \
+ sha2_word32 tmp = (w); \
+ tmp = (tmp >> 16) | (tmp << 16); \
+ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x) { \
+ sha2_word64 tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+ ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n) { \
+ (w)[0] += (sha2_word64)(n); \
+ if ((w)[0] < (n)) { \
+ (w)[1]++; \
+ } \
+}
+
+/*
+ * Macros for copying blocks of memory and for zeroing out ranges
+ * of memory. Using these macros makes it easy to switch from
+ * using memset()/memcpy() and using bzero()/bcopy().
+ *
+ * Please define either SHA2_USE_MEMSET_MEMCPY or define
+ * SHA2_USE_BZERO_BCOPY depending on which function set you
+ * choose to use:
+ */
+#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
+/* Default to memset()/memcpy() if no option is specified */
+#define SHA2_USE_MEMSET_MEMCPY 1
+#endif
+#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
+/* Abort with an error if BOTH options are defined */
+#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
+#endif
+
+#ifdef SHA2_USE_MEMSET_MEMCPY
+#define MEMSET_BZERO(p,l) memset((p), 0, (l))
+#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
+#endif
+#ifdef SHA2_USE_BZERO_BCOPY
+#define MEMSET_BZERO(p,l) bzero((p), (l))
+#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l))
+#endif
+
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
+ * S is a ROTATION) because the SHA-256/384/512 description document
+ * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ * same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) ((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
+#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
+#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void SHA512_Last(SHA512_CTX*);
+void SHA256_Transform(Sha256::detail::Context*, const sha2_word32*);
+void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+const static sha2_word32 K256[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+const static sha2_word32 sha256_initial_hash_value[8] = {
+ 0x6a09e667UL,
+ 0xbb67ae85UL,
+ 0x3c6ef372UL,
+ 0xa54ff53aUL,
+ 0x510e527fUL,
+ 0x9b05688cUL,
+ 0x1f83d9abUL,
+ 0x5be0cd19UL
+};
+
+/* Hash constant words K for SHA-384 and SHA-512: */
+const static sha2_word64 K512[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384 */
+const static sha2_word64 sha384_initial_hash_value[8] = {
+ 0xcbbb9d5dc1059ed8ULL,
+ 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL,
+ 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL,
+ 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL,
+ 0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512 */
+const static sha2_word64 sha512_initial_hash_value[8] = {
+ 0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL
+};
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+
+/*** SHA-256: *********************************************************/
+void SHA256_Init(Sha256::detail::Context* context) {
+ if (context == (Sha256::detail::Context*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha256_initial_hash_value, Sha256::digestLength);
+ MEMSET_BZERO(context->buffer, Sha256::blockLength);
+ context->bitcount = 0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE32(*data++, W256[j]); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + W256[j]; \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + (W256[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h) \
+ s0 = W256[(j+1)&0x0f]; \
+ s0 = sigma0_256(s0); \
+ s1 = W256[(j+14)&0x0f]; \
+ s1 = sigma1_256(s1); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+void SHA256_Transform(Sha256::detail::Context* context, const sha2_word32* data) {
+ sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word32 T1, *W256;
+ int j;
+
+ W256 = (sha2_word32*)context->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+ /* Rounds 0 to 15 (unrolled): */
+ ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds to 64: */
+ do {
+ ROUND256(a,b,c,d,e,f,g,h);
+ ROUND256(h,a,b,c,d,e,f,g);
+ ROUND256(g,h,a,b,c,d,e,f);
+ ROUND256(f,g,h,a,b,c,d,e);
+ ROUND256(e,f,g,h,a,b,c,d);
+ ROUND256(d,e,f,g,h,a,b,c);
+ ROUND256(c,d,e,f,g,h,a,b);
+ ROUND256(b,c,d,e,f,g,h,a);
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Transform(Sha256::detail::Context* context, const sha2_word32* data) {
+ sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word32 T1, T2, *W256;
+ int j;
+
+ W256 = (sha2_word32*)context->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Copy data while converting to host byte order */
+ REVERSE32(*data++,W256[j]);
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-256 compression function to update a..h with copy */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W256[(j+1)&0x0f];
+ s0 = sigma0_256(s0);
+ s1 = W256[(j+14)&0x0f];
+ s1 = sigma1_256(s1);
+
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Update(Sha256::detail::Context* context, const sha2_byte *data, size_t len) {
+ unsigned int freespace, usedspace;
+
+ if (len == 0) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ assert(context != (Sha256::detail::Context*)0 && data != (sha2_byte*)0);
+
+ usedspace = (context->bitcount >> 3) % Sha256::blockLength;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = Sha256::blockLength - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+ context->bitcount += freespace << 3;
+ len -= freespace;
+ data += freespace;
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+ context->bitcount += len << 3;
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= Sha256::blockLength) {
+ /* Process as many complete blocks as we can */
+ SHA256_Transform(context, (sha2_word32*)data);
+ context->bitcount += Sha256::blockLength << 3;
+ len -= Sha256::blockLength;
+ data += Sha256::blockLength;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(context->buffer, data, len);
+ context->bitcount += len << 3;
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+void SHA256_Final(sha2_byte digest[], Sha256::detail::Context* context) {
+ sha2_word32 *d = (sha2_word32*)digest;
+ unsigned int usedspace;
+
+ /* Sanity check: */
+ assert(context != (Sha256::detail::Context*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ usedspace = (context->bitcount >> 3) % Sha256::blockLength;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount,context->bitcount);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < Sha256::blockLength) {
+ MEMSET_BZERO(&context->buffer[usedspace], Sha256::blockLength - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+ }
+ } else {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Set the bit count: */
+ *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+ /* Final transform: */
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE32(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, Sha256::digestLength);
+#endif
+ }
+
+ /* Clean up state data: */
+ MEMSET_BZERO(context, sizeof(Sha256::detail::Context));
+ usedspace = 0;
+}
+
+char *SHA256_End(Sha256::detail::Context* context, char buffer[]) {
+ sha2_byte digest[Sha256::digestLength], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (Sha256::detail::Context*)0);
+
+ if (buffer != (char*)0) {
+ SHA256_Final(digest, context);
+
+ for (i = 0; i < Sha256::digestLength; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(Sha256::detail::Context));
+ }
+ MEMSET_BZERO(digest, Sha256::digestLength);
+ return buffer;
+}
+
+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+ Sha256::detail::Context context;
+
+ SHA256_Init(&context);
+ SHA256_Update(&context, data, len);
+ return SHA256_End(&context, digest);
+}
+
+
+/*** SHA-512: *********************************************************/
+void SHA512_Init(SHA512_CTX* context) {
+ if (context == (SHA512_CTX*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE64(*data++, W512[j]); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + W512[j]; \
+ (d) += T1, \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + (W512[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h) \
+ s0 = W512[(j+1)&0x0f]; \
+ s0 = sigma0_512(s0); \
+ s1 = W512[(j+14)&0x0f]; \
+ s1 = sigma1_512(s1); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, *W512 = (sha2_word64*)context->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+ ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds up to 79: */
+ do {
+ ROUND512(a,b,c,d,e,f,g,h);
+ ROUND512(h,a,b,c,d,e,f,g);
+ ROUND512(g,h,a,b,c,d,e,f);
+ ROUND512(f,g,h,a,b,c,d,e);
+ ROUND512(e,f,g,h,a,b,c,d);
+ ROUND512(d,e,f,g,h,a,b,c);
+ ROUND512(c,d,e,f,g,h,a,b);
+ ROUND512(b,c,d,e,f,g,h,a);
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert TO host byte order */
+ REVERSE64(*data++, W512[j]);
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-512 compression function to update a..h with copy */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W512[(j+1)&0x0f];
+ s0 = sigma0_512(s0);
+ s1 = W512[(j+14)&0x0f];
+ s1 = sigma1_512(s1);
+
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
+ unsigned int freespace, usedspace;
+
+ if (len == 0) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+
+ usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+ ADDINC128(context->bitcount, freespace << 3);
+ len -= freespace;
+ data += freespace;
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+ ADDINC128(context->bitcount, len << 3);
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= SHA512_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ SHA512_Transform(context, (sha2_word64*)data);
+ ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
+ len -= SHA512_BLOCK_LENGTH;
+ data += SHA512_BLOCK_LENGTH;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(context->buffer, data, len);
+ ADDINC128(context->bitcount, len << 3);
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+void SHA512_Last(SHA512_CTX* context) {
+ unsigned int usedspace;
+
+ usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount[0],context->bitcount[0]);
+ REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < SHA512_BLOCK_LENGTH) {
+ MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
+ }
+ } else {
+ /* Prepare for final transform: */
+ MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Store the length of input data (in bits): */
+ *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+ *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+ /* Final transform: */
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+}
+
+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+ sha2_word64 *d = (sha2_word64*)digest;
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ SHA512_Last(context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ MEMSET_BZERO(context, sizeof(SHA512_CTX));
+}
+
+char *SHA512_End(SHA512_CTX* context, char buffer[]) {
+ sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA512_Final(digest, context);
+
+ for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(SHA512_CTX));
+ }
+ MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
+ return buffer;
+}
+
+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
+ SHA512_CTX context;
+
+ SHA512_Init(&context);
+ SHA512_Update(&context, data, len);
+ return SHA512_End(&context, digest);
+}
+
+
+/*** SHA-384: *********************************************************/
+void SHA384_Init(SHA384_CTX* context) {
+ if (context == (SHA384_CTX*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+ SHA512_Update((SHA512_CTX*)context, data, len);
+}
+
+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+ sha2_word64 *d = (sha2_word64*)digest;
+
+ /* Sanity check: */
+ assert(context != (SHA384_CTX*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ SHA512_Last((SHA512_CTX*)context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 6; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ MEMSET_BZERO(context, sizeof(SHA384_CTX));
+}
+
+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
+ sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA384_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA384_Final(digest, context);
+
+ for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(SHA384_CTX));
+ }
+ MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
+ return buffer;
+}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+ SHA384_CTX context;
+
+ SHA384_Init(&context);
+ SHA384_Update(&context, data, len);
+ return SHA384_End(&context, digest);
+}
diff --git a/beast/crypto/impl/sha2/sha2.h b/beast/crypto/impl/sha2/sha2.h
new file mode 100644
index 0000000000..a3c38807d2
--- /dev/null
+++ b/beast/crypto/impl/sha2/sha2.h
@@ -0,0 +1,135 @@
+/*
+ * FILE: sha2.h
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
+ */
+
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+//#ifdef __cplusplus
+//extern "C" {
+//#endif
+
+/*
+ * Import u_intXX_t size_t type definitions from system headers. You
+ * may need to change this, or define these things yourself in this
+ * file.
+ */
+#include
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA256_DIGEST_STRING_LENGTH (Sha256::digestLength * 2 + 1)
+#define SHA384_BLOCK_LENGTH 128
+#define SHA384_DIGEST_LENGTH 48
+#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
+#define SHA512_BLOCK_LENGTH 128
+#define SHA512_DIGEST_LENGTH 64
+#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
+
+/*** SHA-256/384/512 Context Structures *******************************/
+/* NOTE: If your architecture does not define either u_intXX_t types or
+ * uintXX_t (from inttypes.h), you may need to define things by hand
+ * for your system:
+ */
+#if 0
+typedef unsigned char u_int8_t; /* 1-byte (8-bits) */
+typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */
+typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */
+#endif
+/*
+ * Most BSD systems already define u_intXX_t types, as does Linux.
+ * Some systems, however, like Compaq's Tru64 Unix instead can use
+ * uintXX_t types defined by very recent ANSI C standards and included
+ * in the file:
+ *
+ * #include
+ *
+ */
+typedef struct _SHA512_CTX {
+ u_int64_t state[8];
+ u_int64_t bitcount[2];
+ u_int8_t buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+typedef SHA512_CTX SHA384_CTX;
+
+
+/*** SHA-256/384/512 Function Prototypes ******************************/
+#ifndef NOPROTO
+
+void SHA256_Init(Sha256::detail::Context *);
+void SHA256_Update(Sha256::detail::Context*, const u_int8_t*, size_t);
+void SHA256_Final(u_int8_t[Sha256::digestLength], Sha256::detail::Context*);
+char* SHA256_End(Sha256::detail::Context*, char[SHA256_DIGEST_STRING_LENGTH]);
+char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
+
+void SHA384_Init(SHA384_CTX*);
+void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
+void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
+char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
+char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
+
+void SHA512_Init(SHA512_CTX*);
+void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
+void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
+char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
+char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
+
+#else /* NOPROTO */
+
+void SHA256_Init();
+void SHA256_Update();
+void SHA256_Final();
+char* SHA256_End();
+char* SHA256_Data();
+
+void SHA384_Init();
+void SHA384_Update();
+void SHA384_Final();
+char* SHA384_End();
+char* SHA384_Data();
+
+void SHA512_Init();
+void SHA512_Update();
+void SHA512_Final();
+char* SHA512_End();
+char* SHA512_Data();
+
+#endif /* NOPROTO */
+
+//#ifdef __cplusplus
+//}
+//#endif /* __cplusplus */
+
+#endif /* __SHA2_H__ */
+
diff --git a/beast/crypto/impl/sha2/sha2prog.c b/beast/crypto/impl/sha2/sha2prog.c
new file mode 100644
index 0000000000..012701e898
--- /dev/null
+++ b/beast/crypto/impl/sha2/sha2prog.c
@@ -0,0 +1,132 @@
+/*
+ * FILE: sha2prog.c
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "sha2.h"
+
+void usage(char *prog, char *msg) {
+ fprintf(stderr, "%s\nUsage:\t%s [options] []\nOptions:\n\t-256\tGenerate SHA-256 hash\n\t-384\tGenerate SHA-284 hash\n\t-512\tGenerate SHA-512 hash\n\t-ALL\tGenerate all three hashes\n\t-q\tQuiet mode - only output hexadecimal hashes, one per line\n\n", msg, prog);
+ exit(-1);
+}
+
+#define BUFLEN 16384
+
+int main(int argc, char **argv) {
+ int kl, l, fd, ac;
+ int quiet = 0, hash = 0;
+ char *av, *file = (char*)0;
+ FILE *IN = (FILE*)0;
+ SHA256_CTX ctx256;
+ SHA384_CTX ctx384;
+ SHA512_CTX ctx512;
+ unsigned char buf[BUFLEN];
+
+ SHA256_Init(&ctx256);
+ SHA384_Init(&ctx384);
+ SHA512_Init(&ctx512);
+
+ /* Read data from STDIN by default */
+ fd = fileno(stdin);
+
+ ac = 1;
+ while (ac < argc) {
+ if (*argv[ac] == '-') {
+ av = argv[ac] + 1;
+ if (!strcmp(av, "q")) {
+ quiet = 1;
+ } else if (!strcmp(av, "256")) {
+ hash |= 1;
+ } else if (!strcmp(av, "384")) {
+ hash |= 2;
+ } else if (!strcmp(av, "512")) {
+ hash |= 4;
+ } else if (!strcmp(av, "ALL")) {
+ hash = 7;
+ } else {
+ usage(argv[0], "Invalid option.");
+ }
+ ac++;
+ } else {
+ file = argv[ac++];
+ if (ac != argc) {
+ usage(argv[0], "Too many arguments.");
+ }
+ if ((IN = fopen(file, "r")) == NULL) {
+ perror(argv[0]);
+ exit(-1);
+ }
+ fd = fileno(IN);
+ }
+ }
+ if (hash == 0)
+ hash = 7; /* Default to ALL */
+
+ kl = 0;
+ while ((l = read(fd,buf,BUFLEN)) > 0) {
+ kl += l;
+ SHA256_Update(&ctx256, (unsigned char*)buf, l);
+ SHA384_Update(&ctx384, (unsigned char*)buf, l);
+ SHA512_Update(&ctx512, (unsigned char*)buf, l);
+ }
+ if (file) {
+ fclose(IN);
+ }
+
+ if (hash & 1) {
+ SHA256_End(&ctx256, buf);
+ if (!quiet)
+ printf("SHA-256 (%s) = ", file);
+ printf("%s\n", buf);
+ }
+ if (hash & 2) {
+ SHA384_End(&ctx384, buf);
+ if (!quiet)
+ printf("SHA-384 (%s) = ", file);
+ printf("%s\n", buf);
+ }
+ if (hash & 4) {
+ SHA512_End(&ctx512, buf);
+ if (!quiet)
+ printf("SHA-512 (%s) = ", file);
+ printf("%s\n", buf);
+ }
+
+ return 1;
+}
+
diff --git a/beast/crypto/impl/sha2/sha2speed.c b/beast/crypto/impl/sha2/sha2speed.c
new file mode 100644
index 0000000000..2e135750fa
--- /dev/null
+++ b/beast/crypto/impl/sha2/sha2speed.c
@@ -0,0 +1,174 @@
+/*
+ * FILE: sha2speed.c
+ * AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sha2speed.c,v 1.1 2001/11/08 00:02:23 adg Exp adg $
+ */
+
+#include
+#include
+#include
+#include
+
+#include "sha2.h"
+
+#define BUFSIZE 16384
+
+void usage(char *prog) {
+ fprintf(stderr, "Usage:\t%s [] [] []\n", prog);
+ exit(-1);
+}
+
+void printspeed(char *caption, unsigned long bytes, double time) {
+ if (bytes / 1073741824UL > 0) {
+ printf("%s %.4f sec (%.3f GBps)\n", caption, time, (double)bytes/1073741824UL/time);
+ } else if (bytes / 1048576 > 0) {
+ printf("%s %.4f (%.3f MBps)\n", caption, time, (double)bytes/1048576/time);
+ } else if (bytes / 1024 > 0) {
+ printf("%s %.4f (%.3f KBps)\n", caption, time, (double)bytes/1024/time);
+ } else {
+ printf("%s %.4f (%f Bps)\n", caption, time, (double)bytes/time);
+ }
+}
+
+
+int main(int argc, char **argv) {
+ SHA256_CTX c256;
+ SHA384_CTX c384;
+ SHA512_CTX c512;
+ char buf[BUFSIZE];
+ char md[SHA512_DIGEST_STRING_LENGTH];
+ int bytes, blocks, rep, i, j;
+ struct timeval start, end;
+ double t, ave256, ave384, ave512;
+ double best256, best384, best512;
+
+ if (argc > 4) {
+ usage(argv[0]);
+ }
+
+ /* Default to 1024 16K blocks (16 MB) */
+ bytes = 1024 * 1024 * 16;
+ if (argc > 1) {
+ blocks = atoi(argv[1]);
+ }
+ blocks = bytes / BUFSIZE;
+
+ /* Default to 10 repetitions */
+ rep = 10;
+ if (argc > 2) {
+ rep = atoi(argv[2]);
+ }
+
+ /* Set up the input data */
+ if (argc > 3) {
+ memset(buf, atoi(argv[2]), BUFSIZE);
+ } else {
+ memset(buf, 0xb7, BUFSIZE);
+ }
+
+ ave256 = ave384 = ave512 = 0;
+ best256 = best384 = best512 = 100000;
+ for (i = 0; i < rep; i++) {
+ SHA256_Init(&c256);
+ SHA384_Init(&c384);
+ SHA512_Init(&c512);
+
+ gettimeofday(&start, (struct timezone*)0);
+ for (j = 0; j < blocks; j++) {
+ SHA256_Update(&c256, (unsigned char*)buf, BUFSIZE);
+ }
+ if (bytes % BUFSIZE) {
+ SHA256_Update(&c256, (unsigned char*)buf, bytes % BUFSIZE);
+ }
+ SHA256_End(&c256, md);
+ gettimeofday(&end, (struct timezone*)0);
+ t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0;
+ ave256 += t;
+ if (t < best256) {
+ best256 = t;
+ }
+ printf("SHA-256[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave256/(i+1), best256, md);
+
+ gettimeofday(&start, (struct timezone*)0);
+ for (j = 0; j < blocks; j++) {
+ SHA384_Update(&c384, (unsigned char*)buf, BUFSIZE);
+ }
+ if (bytes % BUFSIZE) {
+ SHA384_Update(&c384, (unsigned char*)buf, bytes % BUFSIZE);
+ }
+ SHA384_End(&c384, md);
+ gettimeofday(&end, (struct timezone*)0);
+ t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0;
+ ave384 += t;
+ if (t < best384) {
+ best384 = t;
+ }
+ printf("SHA-384[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave384/(i+1), best384, md);
+
+ gettimeofday(&start, (struct timezone*)0);
+ for (j = 0; j < blocks; j++) {
+ SHA512_Update(&c512, (unsigned char*)buf, BUFSIZE);
+ }
+ if (bytes % BUFSIZE) {
+ SHA512_Update(&c512, (unsigned char*)buf, bytes % BUFSIZE);
+ }
+ SHA512_End(&c512, md);
+ gettimeofday(&end, (struct timezone*)0);
+ t = ((end.tv_sec - start.tv_sec) * 1000000.0 + (end.tv_usec - start.tv_usec)) / 1000000.0;
+ ave512 += t;
+ if (t < best512) {
+ best512 = t;
+ }
+ printf("SHA-512[%d] (%.4f/%.4f/%.4f seconds) = 0x%s\n", i+1, t, ave512/(i+1), best512, md);
+ }
+ ave256 /= rep;
+ ave384 /= rep;
+ ave512 /= rep;
+ printf("\nTEST RESULTS SUMMARY:\nTEST REPETITIONS: %d\n", rep);
+ if (bytes / 1073741824UL > 0) {
+ printf("TEST SET SIZE: %.3f GB\n", (double)bytes/1073741824UL);
+ } else if (bytes / 1048576 > 0) {
+ printf("TEST SET SIZE: %.3f MB\n", (double)bytes/1048576);
+ } else if (bytes /1024 > 0) {
+ printf("TEST SET SIZE: %.3f KB\n", (double)bytes/1024);
+ } else {
+ printf("TEST SET SIZE: %d B\n", bytes);
+ }
+ printspeed("SHA-256 average:", bytes, ave256);
+ printspeed("SHA-256 best: ", bytes, best256);
+ printspeed("SHA-384 average:", bytes, ave384);
+ printspeed("SHA-384 best: ", bytes, best384);
+ printspeed("SHA-512 average:", bytes, ave512);
+ printspeed("SHA-512 best: ", bytes, best512);
+
+ return 1;
+}
+
diff --git a/beast/crypto/impl/sha2/sha2test.pl b/beast/crypto/impl/sha2/sha2test.pl
new file mode 100644
index 0000000000..dc884d8c17
--- /dev/null
+++ b/beast/crypto/impl/sha2/sha2test.pl
@@ -0,0 +1,358 @@
+#!/usr/bin/perl
+#
+# FILE: sha2test.pl
+# AUTHOR: Aaron D. Gifford - http://www.aarongifford.com/
+#
+# Copyright (c) 2001, Aaron D. Gifford
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. Neither the name of the copyright holder nor the names of contributors
+# may be used to endorse or promote products derived from this software
+# without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $Id: sha2test.pl,v 1.1 2001/11/08 00:02:37 adg Exp adg $
+#
+
+sub usage {
+ my ($err) = shift(@_);
+
+ print <] [ [ ...]]
+
+Options:
+ -256 Use SHA-256 hashes during testing
+ -384 Use SHA-384 hashes during testing
+ -512 Use SHA-512 hashes during testing
+ -ALL Use all three hashes during testing
+ -c256 Specify a command to execute to generate a
+ SHA-256 hash. Be sure to include a '%'
+ character which will be replaced by the
+ test vector data filename containing the
+ data to be hashed. This command implies
+ the -256 option.
+ -c384 Specify a command to execute to generate a
+ SHA-384 hash. See above. Implies -384.
+ -c512 Specify a command to execute to generate a
+ SHA-512 hash. See above. Implies -512.
+ -cALL Specify a command to execute that will
+ generate all three hashes at once and output
+ the data in hexadecimal. See above for
+ information about the .
+ This option implies the -ALL option, and
+ also overrides any other command options if
+ present.
+
+By default, this program expects to execute the command ./sha2 within the
+current working directory to generate all hashes. If no test vector
+information files are specified, this program expects to read a series of
+files ending in ".info" within a subdirectory of the current working
+directory called "testvectors".
+
+EOM
+ exit(-1);
+}
+
+$c256 = $c384 = $c512 = $cALL = "";
+$hashes = 0;
+@FILES = ();
+
+# Read all command-line options and files:
+while ($opt = shift(@ARGV)) {
+ if ($opt =~ s/^\-//) {
+ if ($opt eq "256") {
+ $hashes |= 1;
+ } elsif ($opt eq "384") {
+ $hashes |= 2;
+ } elsif ($opt eq "512") {
+ $hashes |= 4;
+ } elsif ($opt =~ /^ALL$/i) {
+ $hashes = 7;
+ } elsif ($opt =~ /^c256$/i) {
+ $hashes |= 1;
+ $opt = $c256 = shift(@ARGV);
+ $opt =~ s/\s+.*$//;
+ if (!$c256 || $c256 !~ /\%/ || !-x $opt) {
+ usage("Missing or invalid command specification for option -c256: $opt\n");
+ }
+ } elsif ($opt =~ /^c384$/i) {
+ $hashes |= 2;
+ $opt = $c384 = shift(@ARGV);
+ $opt =~ s/\s+.*$//;
+ if (!$c384 || $c384 !~ /\%/ || !-x $opt) {
+ usage("Missing or invalid command specification for option -c384: $opt\n");
+ }
+ } elsif ($opt =~ /^c512$/i) {
+ $hashes |= 4;
+ $opt = $c512 = shift(@ARGV);
+ $opt =~ s/\s+.*$//;
+ if (!$c512 || $c512 !~ /\%/ || !-x $opt) {
+ usage("Missing or invalid command specification for option -c512: $opt\n");
+ }
+ } elsif ($opt =~ /^cALL$/i) {
+ $hashes = 7;
+ $opt = $cALL = shift(@ARGV);
+ $opt =~ s/\s+.*$//;
+ if (!$cALL || $cALL !~ /\%/ || !-x $opt) {
+ usage("Missing or invalid command specification for option -cALL: $opt\n");
+ }
+ } else {
+ usage("Unknown/invalid option '$opt'\n");
+ }
+ } else {
+ usage("Invalid, nonexistent, or unreadable file '$opt': $!\n") if (!-f $opt);
+ push(@FILES, $opt);
+ }
+}
+
+# Set up defaults:
+if (!$cALL && !$c256 && !$c384 && !$c512) {
+ $cALL = "./sha2 -ALL %";
+ usage("Required ./sha2 binary executable not found.\n") if (!-x "./sha2");
+}
+$hashes = 7 if (!$hashes);
+
+# Do some sanity checks:
+usage("No command was supplied to generate SHA-256 hashes.\n") if ($hashes & 1 == 1 && !$cALL && !$c256);
+usage("No command was supplied to generate SHA-384 hashes.\n") if ($hashes & 2 == 2 && !$cALL && !$c384);
+usage("No command was supplied to generate SHA-512 hashes.\n") if ($hashes & 4 == 4 && !$cALL && !$c512);
+
+# Default .info files:
+if (scalar(@FILES) < 1) {
+ opendir(DIR, "testvectors") || usage("Unable to scan directory 'testvectors' for vector information files: $!\n");
+ @FILES = grep(/\.info$/, readdir(DIR));
+ closedir(DIR);
+ @FILES = map { s/^/testvectors\//; $_; } @FILES;
+ @FILES = sort(@FILES);
+}
+
+# Now read in each test vector information file:
+foreach $file (@FILES) {
+ $dir = $file;
+ if ($file !~ /\//) {
+ $dir = "./";
+ } else {
+ $dir =~ s/\/[^\/]+$//;
+ $dir .= "/";
+ }
+ open(FILE, "<" . $file) ||
+ usage("Unable to open test vector information file '$file' for reading: $!\n");
+ $vec = { desc => "", file => "", sha256 => "", sha384 => "", sha512 => "" };
+ $data = $field = "";
+ $line = 0;
+ while() {
+ $line++;
+ s/\s*[\r\n]+$//;
+ next if ($field && $field ne "DESCRIPTION" && !$_);
+ if (/^(DESCRIPTION|FILE|SHA256|SHA384|SHA512):$/) {
+ if ($field eq "DESCRIPTION") {
+ $vec->{desc} = $data;
+ } elsif ($field eq "FILE") {
+ $data = $dir . $data if ($data !~ /^\//);
+ $vec->{file} = $data;
+ } elsif ($field eq "SHA256") {
+ $vec->{sha256} = $data;
+ } elsif ($field eq "SHA384") {
+ $vec->{sha384} = $data;
+ } elsif ($field eq "SHA512") {
+ $vec->{sha512} = $data;
+ }
+ $data = "";
+ $field = $1;
+ } elsif ($field eq "DESCRIPTION") {
+ s/^ //;
+ $data .= $_ . "\n";
+ } elsif ($field =~ /^SHA\d\d\d$/) {
+ s/^\s+//;
+ if (!/^([a-f0-9]{32}|[a-f0-9]{64})$/) {
+ usage("Invalid SHA-256/384/512 test vector information " .
+ "file format at line $line of file '$file'\n");
+ }
+ $data .= $_;
+ } elsif ($field eq "FILE") {
+ s/^ //;
+ $data .= $_;
+ } else {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format at line $line of file '$file'\n");
+ }
+ }
+ if ($field eq "DESCRIPTION") {
+ $data = $dir . $data if ($data !~ /^\//);
+ $vec->{desc} = $data;
+ } elsif ($field eq "FILE") {
+ $vec->{file} = $data;
+ } elsif ($field eq "SHA256") {
+ $vec->{sha256} = $data;
+ } elsif ($field eq "SHA384") {
+ $vec->{sha384} = $data;
+ } elsif ($field eq "SHA512") {
+ $vec->{sha512} = $data;
+ } else {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. Missing required fields in file '$file'\n");
+ }
+
+ # Sanity check all entries:
+ if (!$vec->{desc}) {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. Missing required DESCRIPTION field in file '$file'\n");
+ }
+ if (!$vec->{file}) {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. Missing required FILE field in file '$file'\n");
+ }
+ if (! -f $vec->{file}) {
+ usage("The test vector data file (field FILE) name " .
+ "'$vec->{file}' is not a readable file. Check the FILE filed in " .
+ "file '$file'.\n");
+ }
+ if (!($vec->{sha256} || $vec->{sha384} || $vec->{sha512})) {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. There must be at least one SHA256, SHA384, or SHA512 " .
+ "field specified in file '$file'.\n");
+ }
+ if ($vec->{sha256} !~ /^(|[a-f0-9]{64})$/) {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. The SHA256 field is invalid in file '$file'.\n");
+ }
+ if ($vec->{sha384} !~ /^(|[a-f0-9]{96})$/) {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. The SHA384 field is invalid in file '$file'.\n");
+ }
+ if ($vec->{sha512} !~ /^(|[a-f0-9]{128})$/) {
+ usage("Invalid SHA-256/384/512 test vector information file " .
+ "format. The SHA512 field is invalid in file '$file'.\n");
+ }
+ close(FILE);
+ if ($hashes & (($vec->{sha256} ? 1 : 0) | ($vec->{sha384} ? 2 : 0) | ($vec->{sha512} ? 4 : 0))) {
+ push(@VECTORS, $vec);
+ }
+}
+
+usage("There were no test vectors for the specified hash(es) in any of the test vector information files you specified.\n") if (scalar(@VECTORS) < 1);
+
+$num = $errors = $error256 = $error384 = $error512 = $tests = $test256 = $test384 = $test512 = 0;
+foreach $vec (@VECTORS) {
+ $num++;
+ print "TEST VECTOR #$num:\n";
+ print "\t" . join("\n\t", split(/\n/, $vec->{desc})) . "\n";
+ print "VECTOR DATA FILE:\n\t$vec->{file}\n";
+ $sha256 = $sha384 = $sha512 = "";
+ if ($cALL) {
+ $prog = $cALL;
+ $prog =~ s/\%/'$vec->{file}'/g;
+ @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`));
+ ($sha256) = grep(/(^[a-fA-F0-9]{64}$|^[a-fA-F0-9]{64}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{64}$|[^a-fA-F0-9][a-fA-F0-9]{64}[^a-fA-F0-9])/, @SHA);
+ ($sha384) = grep(/(^[a-fA-F0-9]{96}$|^[a-fA-F0-9]{96}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{96}$|[^a-fA-F0-9][a-fA-F0-9]{96}[^a-fA-F0-9])/, @SHA);
+ ($sha512) = grep(/(^[a-fA-F0-9]{128}$|^[a-fA-F0-9]{128}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{128}$|[^a-fA-F0-9][a-fA-F0-9]{128}[^a-fA-F0-9])/, @SHA);
+ } else {
+ if ($c256) {
+ $prog = $c256;
+ $prog =~ s/\%/'$vec->{file}'/g;
+ @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`));
+ ($sha256) = grep(/(^[a-fA-F0-9]{64}$|^[a-fA-F0-9]{64}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{64}$|[^a-fA-F0-9][a-fA-F0-9]{64}[^a-fA-F0-9])/, @SHA);
+ }
+ if ($c384) {
+ $prog = $c384;
+ $prog =~ s/\%/'$vec->{file}'/g;
+ @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`));
+ ($sha384) = grep(/(^[a-fA-F0-9]{96}$|^[a-fA-F0-9]{96}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{96}$|[^a-fA-F0-9][a-fA-F0-9]{96}[^a-fA-F0-9])/, @SHA);
+ }
+ if ($c512) {
+ $prog = $c512;
+ $prog =~ s/\%/'$vec->{file}'/g;
+ @SHA = grep(/[a-fA-f0-9]{64,128}/, split(/\n/, `$prog`));
+ ($sha512) = grep(/(^[a-fA-F0-9]{128}$|^[a-fA-F0-9]{128}[^a-fA-F0-9]|[^a-fA-F0-9][a-fA-F0-9]{128}$|[^a-fA-F0-9][a-fA-F0-9]{128}[^a-fA-F0-9])/, @SHA);
+ }
+ }
+ usage("Unable to generate any hashes for file '$vec->{file}'!\n") if (!$sha256 && !$sha384 && $sha512);
+ $sha256 =~ tr/A-F/a-f/;
+ $sha384 =~ tr/A-F/a-f/;
+ $sha512 =~ tr/A-F/a-f/;
+ $sha256 =~ s/^.*([a-f0-9]{64}).*$/$1/;
+ $sha384 =~ s/^.*([a-f0-9]{96}).*$/$1/;
+ $sha512 =~ s/^.*([a-f0-9]{128}).*$/$1/;
+
+ if ($sha256 && $hashes & 1 == 1) {
+ if ($vec->{sha256} eq $sha256) {
+ print "SHA256 MATCHES:\n\t$sha256\n"
+ } else {
+ print "SHA256 DOES NOT MATCH:\n\tEXPECTED:\n\t\t$vec->{sha256}\n" .
+ "\tGOT:\n\t\t$sha256\n\n";
+ $error256++;
+ }
+ $test256++;
+ }
+ if ($sha384 && $hashes & 2 == 2) {
+ if ($vec->{sha384} eq $sha384) {
+ print "SHA384 MATCHES:\n\t" . substr($sha384, 0, 64) . "\n\t" .
+ substr($sha384, -32) . "\n";
+ } else {
+ print "SHA384 DOES NOT MATCH:\n\tEXPECTED:\n\t\t" .
+ substr($vec->{sha384}, 0, 64) . "\n\t\t" .
+ substr($vec->{sha384}, -32) . "\n\tGOT:\n\t\t" .
+ substr($sha384, 0, 64) . "\n\t\t" . substr($sha384, -32) . "\n\n";
+ $error384++;
+ }
+ $test384++;
+ }
+ if ($sha512 && $hashes & 4 == 4) {
+ if ($vec->{sha512} eq $sha512) {
+ print "SHA512 MATCHES:\n\t" . substr($sha512, 0, 64) . "\n\t" .
+ substr($sha512, -64) . "\n";
+ } else {
+ print "SHA512 DOES NOT MATCH:\n\tEXPECTED:\n\t\t" .
+ substr($vec->{sha512}, 0, 64) . "\n\t\t" .
+ substr($vec->{sha512}, -32) . "\n\tGOT:\n\t\t" .
+ substr($sha512, 0, 64) . "\n\t\t" . substr($sha512, -64) . "\n\n";
+ $error512++;
+ }
+ $test512++;
+ }
+}
+
+$errors = $error256 + $error384 + $error512;
+$tests = $test256 + $test384 + $test512;
+print "\n\n===== RESULTS ($num VECTOR DATA FILES HASHED) =====\n\n";
+print "HASH TYPE\tNO. OF TESTS\tPASSED\tFAILED\n";
+print "---------\t------------\t------\t------\n";
+if ($test256) {
+ $pass = $test256 - $error256;
+ print "SHA-256\t\t".substr(" $test256", -12)."\t".substr(" $pass", -6)."\t".substr(" $error256", -6)."\n";
+}
+if ($test384) {
+ $pass = $test384 - $error384;
+ print "SHA-384\t\t".substr(" $test384", -12)."\t".substr(" $pass", -6)."\t".substr(" $error384", -6)."\n";
+}
+if ($test512) {
+ $pass = $test512 - $error512;
+ print "SHA-512\t\t".substr(" $test512", -12)."\t".substr(" $pass", -6)."\t".substr(" $error512", -6)."\n";
+}
+print "----------------------------------------------\n";
+$pass = $tests - $errors;
+print "TOTAL: ".substr(" $tests", -12)."\t".substr(" $pass", -6)."\t".substr(" $errors", -6)."\n\n";
+print "NO ERRORS! ALL TESTS WERE SUCCESSFUL!\n\n" if (!$errors);
+
diff --git a/beast/intrusive/IntrusiveArray.h b/beast/intrusive/IntrusiveArray.h
new file mode 100644
index 0000000000..53fbe0b057
--- /dev/null
+++ b/beast/intrusive/IntrusiveArray.h
@@ -0,0 +1,187 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of Beast: https://github.com/vinniefalco/Beast
+ Copyright 2013, Vinnie Falco
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+//==============================================================================
+
+#ifndef BEAST_INTRUSIVE_INTRUSIVEARRAY_H_INCLUDED
+#define BEAST_INTRUSIVE_INTRUSIVEARRAY_H_INCLUDED
+
+#include "../Config.h"
+
+#include
+#include
+#include
+#include
+
+namespace beast {
+
+/** A run-time fixed size array that references outside storage.
+ The interface tries to follow std::vector as closely as possible within
+ the limitations of a fixed size and unowned storage.
+*/
+template
+class IntrusiveArray
+{
+private:
+ T* m_begin;
+ T* m_end;
+
+public:
+ typedef T value_type;
+ typedef T* iterator;
+ typedef T const* const_iterator;
+ typedef T& reference;
+ typedef T const& const_reference;
+ typedef std::size_t size_type;
+ typedef std::ptrdiff_t difference_type;
+
+ // Calling methods on a default constructed
+ // array results in undefined behavior!
+ //
+ IntrusiveArray ()
+ : m_begin (nullptr), m_end (nullptr)
+ { }
+ IntrusiveArray (T* begin, T* end)
+ : m_begin (begin), m_end (end)
+ { }
+ IntrusiveArray (IntrusiveArray const& other)
+ : m_begin (other.m_begin), m_end (other.m_end)
+ { }
+ IntrusiveArray (std::vector const& v)
+ : m_begin (&v.front()), m_end (&v.back()+1)
+ { }
+ IntrusiveArray (std::vector & v)
+ : m_begin (&v.front()), m_end (&v.back()+1)
+ { }
+ IntrusiveArray& operator= (IntrusiveArray const& other)
+ {
+ m_begin = other.m_begin;
+ m_end = other.m_end;
+ return *this;
+ }
+
+ // iterators
+ iterator begin() { return m_begin; }
+ const_iterator begin() const { return m_begin; }
+ const_iterator cbegin() const { return m_begin; }
+ iterator end() { return m_end; }
+ const_iterator end() const { return m_end; }
+ const_iterator cend() const { return m_end; }
+
+ typedef std::reverse_iterator reverse_iterator;
+ typedef std::reverse_iterator const_reverse_iterator;
+
+ reverse_iterator rbegin() { return reverse_iterator(end()); }
+ const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const { return const_reverse_iterator(end()); }
+ reverse_iterator rend() { return reverse_iterator(begin()); }
+ const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const { return const_reverse_iterator(begin()); }
+
+ reference operator[](size_type i)
+ {
+ bassert (i < size());
+ return m_begin[i];
+ }
+
+ const_reference operator[](size_type i) const
+ {
+ bassert (i < size());
+ return m_begin[i];
+ }
+
+ reference at(size_type i) { rangecheck(i); return m_begin[i]; }
+ const_reference at(size_type i) const { rangecheck(i); return m_begin[i]; }
+
+ reference front() { return m_begin[0]; }
+ reference back() { return m_end[-1]; }
+ const_reference front () const { return m_begin; }
+ const_reference back() const { return m_end[-1]; }
+
+ size_type size() const { return std::distance (m_begin, m_end); }
+ bool empty() const { return m_begin == m_end; }
+
+ T const* data() const { return m_begin; }
+ T* data() { return m_begin; }
+ T* c_array() { return m_begin; }
+
+ void assign (T const& value) { fill (value); }
+
+ void fill (T const& value)
+ {
+ std::fill_n (begin(), size(), value);
+ }
+
+ void clear ()
+ {
+ fill (T ());
+ }
+
+ void rangecheck (size_type i)
+ {
+ if (i >= size())
+ throw std::out_of_range ("IntrusiveArray<>: index out of range");
+ }
+};
+
+//------------------------------------------------------------------------------
+
+template
+bool operator== (IntrusiveArray const& lhs, IntrusiveArray const& rhs)
+{
+ if ((lhs.begin() == rhs.begin()) && (lhs.end() == rhs.end()))
+ return true;
+ if (lhs.size() != rhs.size())
+ return false;
+ return std::equal (lhs.begin(), lhs.end(), rhs.begin());
+}
+
+template
+bool operator!= (IntrusiveArray const& lhs, IntrusiveArray const& rhs)
+{
+ return !(lhs==rhs);
+}
+
+template
+bool operator< (IntrusiveArray const& lhs, IntrusiveArray const& rhs)
+{
+ if ((lhs.begin() == rhs.begin()) && (lhs.end() == rhs.end()))
+ return false;
+ return std::lexicographical_compare (lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
+
+template
+bool operator> (IntrusiveArray const& lhs, IntrusiveArray const& rhs)
+{
+ return rhs
+bool operator<= (IntrusiveArray const& lhs, IntrusiveArray const& rhs)
+{
+ return !(rhs
+bool operator>= (IntrusiveArray const& lhs, IntrusiveArray const& rhs)
+{
+ return !(lhs= (IPEndpoint const& lhs, IPEndpoint const& rhs);
/** Output stream conversions. */
/** @{ */
-std::ostream& operator<< (std::ostream &os, IPEndpoint::V4 const& addr);
-std::ostream& operator<< (std::ostream &os, IPEndpoint::V6 const& addr);
-std::ostream& operator<< (std::ostream &os, IPEndpoint const& ep);
+std::ostream& operator<< (std::ostream& os, IPEndpoint::V4 const& addr);
+std::ostream& operator<< (std::ostream& os, IPEndpoint::V6 const& addr);
+std::ostream& operator<< (std::ostream& os, IPEndpoint const& ep);
/** @} */
/** Input stream conversions. */
/** @{ */
-std::istream& operator>> (std::istream &is, IPEndpoint::V4& addr);
-std::istream& operator>> (std::istream &is, IPEndpoint& ep);
+std::istream& operator>> (std::istream& is, IPEndpoint::V4& addr);
+std::istream& operator>> (std::istream& is, IPEndpoint& ep);
//std::istream& operator>> (std::istream &is, IPEndpoint::V6&);
/** @} */
diff --git a/modules/beast_crypto/math/BinaryEncoding.cpp b/modules/beast_crypto/math/BinaryEncoding.cpp
index c67e4396c7..198a6b7b86 100644
--- a/modules/beast_crypto/math/BinaryEncoding.cpp
+++ b/modules/beast_crypto/math/BinaryEncoding.cpp
@@ -127,7 +127,7 @@ public:
uint8 const* src (v.cbegin()-1);
char const* const tab (alphabet().c_str());
s.reserve (Bytes * 2);
- for (std::size_t bytes (v.sizeInBytes);bytes--;)
+ for (std::size_t bytes (v.size);bytes--;)
{
uint8 const v (*++src);
s.push_back (tab [v>>4]);
@@ -280,7 +280,7 @@ public:
{
typedef UnsignedInteger UInt;
UInt v0;
- random().fillBitsRandomly (v0.begin(), UInt::sizeInBytes);
+ random().fillBitsRandomly (v0.begin(), UInt::size);
std::string const good (HexEncoding::encode (v0));
UInt v1;
@@ -351,7 +351,7 @@ public:
for (int i = 0; i < 50; ++i)
{
UInt v1;
- random().fillBitsRandomly (v1.begin(), UInt::sizeInBytes);
+ random().fillBitsRandomly (v1.begin(), UInt::size);
std::string const s1 (BinaryEncoding::encode (v1, c));
UInt v2;
diff --git a/modules/beast_crypto/math/UnsignedInteger.h b/modules/beast_crypto/math/UnsignedInteger.h
index 024d5c2b24..df17ef6520 100644
--- a/modules/beast_crypto/math/UnsignedInteger.h
+++ b/modules/beast_crypto/math/UnsignedInteger.h
@@ -32,12 +32,8 @@ template
class UnsignedInteger : public SafeBool >
{
public:
- enum
- {
- /** Constant for determining the number of bytes.
- */
- sizeInBytes = Bytes
- };
+ /** Constant for determining the number of bytes. */
+ static std::size_t const size = Bytes;
// The underlying integer type we use when converting to calculation format.
typedef uint32 IntCalcType;
@@ -46,17 +42,16 @@ public:
typedef UnsignedIntegerCalc CalcType;
// Standard container compatibility
- typedef uint8 ValueType;
- typedef ValueType* iterator;
- typedef ValueType const* const_iterator;
+ typedef uint8 value_type;
+ typedef value_type* iterator;
+ typedef value_type const* const_iterator;
/** Hardened hash function for use with HashMap.
The seed is used to make the hash unpredictable. This prevents
attackers from exploiting crafted inputs to produce degenerate
containers.
- @see HashMap
*/
- class HashFunction
+ class hasher
{
public:
/** Construct a hash function
@@ -64,23 +59,16 @@ public:
will be generated from the system
@param seedToUse An optional seed to use.
*/
- explicit HashFunction (HashValue seedToUse = Random::getSystemRandom ().nextInt ())
+ explicit hasher (HashValue seedToUse = Random::getSystemRandom ().nextInt ())
: m_seed (seedToUse)
{
}
/** Generates a simple hash from an UnsignedInteger. */
- HashValue generateHash (UnsignedInteger const& key) const
- {
- HashValue hash;
- Murmur::Hash (key.cbegin (), key.sizeInBytes, m_seed, &hash);
- return hash;
- }
-
HashValue operator() (UnsignedInteger const& key) const
{
HashValue hash;
- Murmur::Hash (key.cbegin (), key.sizeInBytes, m_seed, &hash);
+ Murmur::Hash (key.cbegin (), key.size, m_seed, &hash);
return hash;
}
@@ -88,6 +76,16 @@ public:
HashValue m_seed;
};
+ /** Determins if two UnsignedInteger objects are equal. */
+ class equal
+ {
+ public:
+ bool operator() (UnsignedInteger const& lhs, UnsignedInteger const& rhs) const
+ {
+ return lhs.compare (rhs) == 0;
+ }
+ };
+
//--------------------------------------------------------------------------
/** Construct the object.
@@ -114,11 +112,12 @@ public:
std::memcpy (begin(), buf, Bytes);
}
- template
- explicit UnsignedInteger (T const* buf)
+ template
+ UnsignedInteger (InputIt first, InputIt last)
{
m_values [0] = 0; // clear any pad bytes
- std::memcpy (begin(), buf, Bytes);
+ check_precondition (std::distance (first, last) == size);
+ std::copy (first, last, begin());
}
/** @} */
@@ -133,20 +132,19 @@ public:
/** Create from an integer type.
@invariant IntegerType must be an unsigned integer type.
*/
- template
- static UnsignedInteger createFromInteger (IntegerType value)
+ template
+ static UnsignedInteger createFromInteger (UnsignedIntegralType value)
{
- static_bassert (Bytes >= sizeof (IntegerType));
+ static_bassert (Bytes >= sizeof (UnsignedIntegralType));
UnsignedInteger result;
- value = toNetworkByteOrder (value);
+ value = toNetworkByteOrder (value);
result.clear ();
std::memcpy (result.end () - sizeof (value), &value, bmin (Bytes, sizeof (value)));
return result;
}
- /** Construct with a filled value.
- */
- static UnsignedInteger createFilled (ValueType value)
+ /** Construct with a filled value. */
+ static UnsignedInteger createFilled (value_type value)
{
UnsignedInteger result;
result.fill (value);
@@ -154,7 +152,7 @@ public:
}
/** Fill with a particular byte value. */
- void fill (ValueType value)
+ void fill (value_type value)
{
IntCalcType c;
memset (&c, value, sizeof (c));
@@ -283,15 +281,15 @@ public:
private:
static std::size_t const CalcCount = (Bytes + sizeof (IntCalcType) - 1) / sizeof (IntCalcType);
- ValueType* get ()
+ value_type* get ()
{
- return (reinterpret_cast (&m_values [0])) +
+ return (reinterpret_cast (&m_values [0])) +
((sizeof(IntCalcType)-(Bytes&(sizeof(IntCalcType)-1)))&(sizeof(IntCalcType)-1));
}
- ValueType const* get () const
+ value_type const* get () const
{
- return (reinterpret_cast (&m_values [0])) +
+ return (reinterpret_cast (&m_values [0])) +
((sizeof(IntCalcType)-(Bytes&(sizeof(IntCalcType)-1)))&(sizeof(IntCalcType)-1));
}