diff --git a/changelog.md b/changelog.md index 847d4695ea..c8978f224d 100644 --- a/changelog.md +++ b/changelog.md @@ -15,9 +15,12 @@ HEAD conflicts with similarly named macros in some operating systems. If you are using the WebSocket++ provided 64 bit host/network byte order functions you will need to switch to the prefixed versions. -- BREAKING UTILITY CHANGE: The signature of the `base64_encode` has changed from +- BREAKING UTILITY CHANGE: The signature of `base64_encode` has changed from `websocketpp::base64_encode(unsigned char const *, unsigned int)` to `websocketpp::base64_encode(unsigned char const *, size_t)`. +- BREAKING UTILITY CHANGE: The signature of `sha1::calc` has changed from + `websocketpp::sha1::calc(void const *, int, unsigned char *)` to + `websocketpp::sha1::calc(void const *, size_t, unsigned char *)` - Feature: Adds incomplete `minimal_server` and `minimal_client` configs that can be used to build custom configs without pulling in the dependencies of `core` or `core_client`. These configs will offer a stable base config to diff --git a/websocketpp/sha1/sha1.hpp b/websocketpp/sha1/sha1.hpp index 3c73db84d7..df15a5f485 100755 --- a/websocketpp/sha1/sha1.hpp +++ b/websocketpp/sha1/sha1.hpp @@ -1,6 +1,6 @@ /* ***** -sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the shallsha1 +sha1.hpp is a repackaging of the sha1.cpp and sha1.h files from the smallsha1 library (http://code.google.com/p/smallsha1/) into a single header suitable for use as a header only library. This conversion was done by Peter Thorson (webmaster@zaphoyd.com) in 2013. All modifications to the code are redistributed @@ -39,111 +39,118 @@ under the same license as the original, which is listed below. namespace websocketpp { namespace sha1 { - namespace // local +namespace { // local + +// Rotate an integer value to left. +inline unsigned int rol(unsigned int value, unsigned int steps) { + return ((value << steps) | (value >> (32 - steps))); +} + +// Sets the first 16 integers in the buffert to zero. +// Used for clearing the W buffert. +inline void clearWBuffert(unsigned int * buffert) +{ + for (int pos = 16; --pos >= 0;) { - // Rotate an integer value to left. - inline unsigned int rol(unsigned int value, unsigned int steps) { - return ((value << steps) | (value >> (32 - steps))); - } + buffert[pos] = 0; + } +} - // Sets the first 16 integers in the buffert to zero. - // Used for clearing the W buffert. - inline void clearWBuffert(unsigned int * buffert) - { - for (int pos = 16; --pos >= 0;) - { - buffert[pos] = 0; - } - } +inline void innerHash(unsigned int * result, unsigned int * w) +{ + unsigned int a = result[0]; + unsigned int b = result[1]; + unsigned int c = result[2]; + unsigned int d = result[3]; + unsigned int e = result[4]; - inline void innerHash(unsigned int * result, unsigned int * w) - { - unsigned int a = result[0]; - unsigned int b = result[1]; - unsigned int c = result[2]; - unsigned int d = result[3]; - unsigned int e = result[4]; + int round = 0; - int round = 0; + #define sha1macro(func,val) \ + { \ + const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ + e = d; \ + d = c; \ + c = rol(b, 30); \ + b = a; \ + a = t; \ + } - #define sha1macro(func,val) \ - { \ - const unsigned int t = rol(a, 5) + (func) + e + val + w[round]; \ - e = d; \ - d = c; \ - c = rol(b, 30); \ - b = a; \ - a = t; \ - } + while (round < 16) + { + sha1macro((b & c) | (~b & d), 0x5a827999) + ++round; + } + while (round < 20) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro((b & c) | (~b & d), 0x5a827999) + ++round; + } + while (round < 40) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro(b ^ c ^ d, 0x6ed9eba1) + ++round; + } + while (round < 60) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) + ++round; + } + while (round < 80) + { + w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); + sha1macro(b ^ c ^ d, 0xca62c1d6) + ++round; + } - while (round < 16) - { - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 20) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (~b & d), 0x5a827999) - ++round; - } - while (round < 40) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0x6ed9eba1) - ++round; - } - while (round < 60) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro((b & c) | (b & d) | (c & d), 0x8f1bbcdc) - ++round; - } - while (round < 80) - { - w[round] = rol((w[round - 3] ^ w[round - 8] ^ w[round - 14] ^ w[round - 16]), 1); - sha1macro(b ^ c ^ d, 0xca62c1d6) - ++round; - } + #undef sha1macro - #undef sha1macro + result[0] += a; + result[1] += b; + result[2] += c; + result[3] += d; + result[4] += e; +} - result[0] += a; - result[1] += b; - result[2] += c; - result[3] += d; - result[4] += e; - } - } // namespace +} // namespace - /** - @param src points to any kind of data to be hashed. - @param bytelength the number of bytes to hash from the src pointer. - @param hash should point to a buffer of at least 20 bytes of size for storing the sha1 result in. - */ - inline void calc(const void* src, const int bytelength, unsigned char* hash) { - // Init the result array. - unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476, 0xc3d2e1f0 }; +/// Calculate a SHA1 hash +/** + * @param src points to any kind of data to be hashed. + * @param bytelength the number of bytes to hash from the src pointer. + * @param hash should point to a buffer of at least 20 bytes of size for storing + * the sha1 result in. + */ +inline void calc(void const * src, size_t bytelength, unsigned char * hash) { + // Init the result array. + unsigned int result[5] = { 0x67452301, 0xefcdab89, 0x98badcfe, + 0x10325476, 0xc3d2e1f0 }; - // Cast the void src pointer to be the byte array we can work with. - const unsigned char* sarray = (const unsigned char*) src; + // Cast the void src pointer to be the byte array we can work with. + unsigned char const * sarray = (unsigned char const *) src; - // The reusable round buffer - unsigned int w[80]; + // The reusable round buffer + unsigned int w[80]; - // Loop through all complete 64byte blocks. - const int endOfFullBlocks = bytelength - 64; - int endCurrentBlock; - int currentBlock = 0; + // Loop through all complete 64byte blocks. - while (currentBlock <= endOfFullBlocks) - { + size_t endCurrentBlock; + size_t currentBlock = 0; + + if (bytelength >= 64) { + size_t const endOfFullBlocks = bytelength - 64; + + while (currentBlock <= endOfFullBlocks) { endCurrentBlock = currentBlock + 64; // Init the round buffer with the 64 byte block data. for (int roundPos = 0; currentBlock < endCurrentBlock; currentBlock += 4) { - // This line will swap endian on big endian and keep endian on little endian. + // This line will swap endian on big endian and keep endian on + // little endian. w[roundPos++] = (unsigned int) sarray[currentBlock + 3] | (((unsigned int) sarray[currentBlock + 2]) << 8) | (((unsigned int) sarray[currentBlock + 1]) << 16) @@ -151,31 +158,31 @@ namespace sha1 { } innerHash(result, w); } - - // Handle the last and not full 64 byte block if existing. - endCurrentBlock = bytelength - currentBlock; - clearWBuffert(w); - int lastBlockBytes = 0; - for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) - { - w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); - } - w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); - if (endCurrentBlock >= 56) - { - innerHash(result, w); - clearWBuffert(w); - } - w[15] = bytelength << 3; - innerHash(result, w); - - // Store hash in result pointer, and make sure we get in in the correct order on both endian models. - for (int hashByte = 20; --hashByte >= 0;) - { - hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff; - } } + // Handle the last and not full 64 byte block if existing. + endCurrentBlock = bytelength - currentBlock; + clearWBuffert(w); + int lastBlockBytes = 0; + for (;lastBlockBytes < endCurrentBlock; ++lastBlockBytes) { + w[lastBlockBytes >> 2] |= (unsigned int) sarray[lastBlockBytes + currentBlock] << ((3 - (lastBlockBytes & 3)) << 3); + } + + w[lastBlockBytes >> 2] |= 0x80 << ((3 - (lastBlockBytes & 3)) << 3); + if (endCurrentBlock >= 56) { + innerHash(result, w); + clearWBuffert(w); + } + w[15] = bytelength << 3; + innerHash(result, w); + + // Store hash in result pointer, and make sure we get in in the correct + // order on both endian models. + for (int hashByte = 20; --hashByte >= 0;) { + hash[hashByte] = (result[hashByte >> 2] >> (((3 - hashByte) & 0x3) << 3)) & 0xff; + } +} + } // namespace sha1 } // namespace websocketpp