diff options
Diffstat (limited to 'lib/libUPnP/Neptune/Source/Core/NptDigest.cpp')
-rw-r--r-- | lib/libUPnP/Neptune/Source/Core/NptDigest.cpp | 685 |
1 files changed, 685 insertions, 0 deletions
diff --git a/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp b/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp new file mode 100644 index 0000000..4e7fb74 --- /dev/null +++ b/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp @@ -0,0 +1,685 @@ +/***************************************************************** +| +| Neptune - Message Digests +| +| Copyright (c) 2002-2010, Axiomatic Systems, LLC. +| All rights reserved. +| +| Redistribution and use in source and binary forms, with or without +| modification, are permitted provided that the following conditions are met: +| * Redistributions of source code must retain the above copyright +| notice, this list of conditions and the following disclaimer. +| * 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. +| * Neither the name of Axiomatic Systems nor the +| names of its contributors may be used to endorse or promote products +| derived from this software without specific prior written permission. +| +| THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''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 AXIOMATIC SYSTEMS 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. +| + ****************************************************************/ + +/* + Portions of this code are based on the code of LibTomCrypt + that was released into public domain by Tom St Denis. +*/ + +/*---------------------------------------------------------------------- +| includes ++---------------------------------------------------------------------*/ +#include "NptDigest.h" +#include "NptUtils.h" + +/*---------------------------------------------------------------------- +| constants ++---------------------------------------------------------------------*/ +#define NPT_BASIC_DIGEST_BLOCK_SIZE 64 + +/*---------------------------------------------------------------------- +| macros ++---------------------------------------------------------------------*/ +#define NPT_Digest_ROL(x, y) \ +( (((NPT_UInt32)(x) << (y)) | (((NPT_UInt32)(x) & 0xFFFFFFFFUL) >> (32 - (y)))) & 0xFFFFFFFFUL) +#define NPT_Digest_ROR(x, y) \ +( ((((NPT_UInt32)(x)&0xFFFFFFFFUL)>>(NPT_UInt32)((y)&31)) | ((NPT_UInt32)(x)<<(NPT_UInt32)(32-((y)&31)))) & 0xFFFFFFFFUL) + +#define NPT_Sha1_F0(x,y,z) (z ^ (x & (y ^ z))) +#define NPT_Sha1_F1(x,y,z) (x ^ y ^ z) +#define NPT_Sha1_F2(x,y,z) ((x & y) | (z & (x | y))) +#define NPT_Sha1_F3(x,y,z) (x ^ y ^ z) + +#define NPT_Sha1_FF0(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F0(b,c,d) + e + W[i] + 0x5a827999UL); b = NPT_Digest_ROL(b, 30); +#define NPT_Sha1_FF1(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F1(b,c,d) + e + W[i] + 0x6ed9eba1UL); b = NPT_Digest_ROL(b, 30); +#define NPT_Sha1_FF2(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F2(b,c,d) + e + W[i] + 0x8f1bbcdcUL); b = NPT_Digest_ROL(b, 30); +#define NPT_Sha1_FF3(a,b,c,d,e,i) e = (NPT_Digest_ROL(a, 5) + NPT_Sha1_F3(b,c,d) + e + W[i] + 0xca62c1d6UL); b = NPT_Digest_ROL(b, 30); + +#define NPT_Sha256_Ch(x,y,z) (z ^ (x & (y ^ z))) +#define NPT_Sha256_Maj(x,y,z) (((x | y) & z) | (x & y)) +#define NPT_Sha256_S(x, n) NPT_Digest_ROR((x),(n)) +#define NPT_Sha256_R(x, n) (((x)&0xFFFFFFFFUL)>>(n)) +#define NPT_Sha256_Sigma0(x) (NPT_Sha256_S(x, 2) ^ NPT_Sha256_S(x, 13) ^ NPT_Sha256_S(x, 22)) +#define NPT_Sha256_Sigma1(x) (NPT_Sha256_S(x, 6) ^ NPT_Sha256_S(x, 11) ^ NPT_Sha256_S(x, 25)) +#define NPT_Sha256_Gamma0(x) (NPT_Sha256_S(x, 7) ^ NPT_Sha256_S(x, 18) ^ NPT_Sha256_R(x, 3)) +#define NPT_Sha256_Gamma1(x) (NPT_Sha256_S(x, 17) ^ NPT_Sha256_S(x, 19) ^ NPT_Sha256_R(x, 10)) + + +#define NPT_Md5_F(x,y,z) (z ^ (x & (y ^ z))) +#define NPT_Md5_G(x,y,z) (y ^ (z & (y ^ x))) +#define NPT_Md5_H(x,y,z) (x ^ y ^ z) +#define NPT_Md5_I(x,y,z) (y ^ (x | (~z))) + +#define NPT_Md5_FF(a,b,c,d,M,s,t) \ + a = (a + NPT_Md5_F(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b; + +#define NPT_Md5_GG(a,b,c,d,M,s,t) \ + a = (a + NPT_Md5_G(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b; + +#define NPT_Md5_HH(a,b,c,d,M,s,t) \ + a = (a + NPT_Md5_H(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b; + +#define NPT_Md5_II(a,b,c,d,M,s,t) \ + a = (a + NPT_Md5_I(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b; + +/*---------------------------------------------------------------------- +| NPT_BasicDigest ++---------------------------------------------------------------------*/ +class NPT_BasicDigest : public NPT_Digest +{ +public: + NPT_BasicDigest(); + + // NPT_Digest methods + virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size); + +protected: + // methods + NPT_Result ComputeDigest(NPT_UInt32* state, + NPT_Cardinal state_count, + bool big_endian, + NPT_DataBuffer& digest); + virtual void CompressBlock(const NPT_UInt8* block) = 0; + + // members + NPT_UInt64 m_Length; + NPT_UInt32 m_Pending; + NPT_UInt8 m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE]; +}; + +/*---------------------------------------------------------------------- +| NPT_BasicDigest::NPT_BasicDigest ++---------------------------------------------------------------------*/ +NPT_BasicDigest::NPT_BasicDigest() : + m_Length(0), + m_Pending(0) +{ +} + +/*---------------------------------------------------------------------- +| NPT_BasicDigest::Update ++---------------------------------------------------------------------*/ +NPT_Result +NPT_BasicDigest::Update(const NPT_UInt8* data, NPT_Size data_size) +{ + while (data_size > 0) { + if (m_Pending == 0 && data_size >= NPT_BASIC_DIGEST_BLOCK_SIZE) { + CompressBlock(data); + m_Length += NPT_BASIC_DIGEST_BLOCK_SIZE * 8; + data += NPT_BASIC_DIGEST_BLOCK_SIZE; + data_size -= NPT_BASIC_DIGEST_BLOCK_SIZE; + } else { + unsigned int chunk = data_size; + if (chunk > (NPT_BASIC_DIGEST_BLOCK_SIZE - m_Pending)) { + chunk = NPT_BASIC_DIGEST_BLOCK_SIZE - m_Pending; + } + NPT_CopyMemory(&m_Buffer[m_Pending], data, chunk); + m_Pending += chunk; + data += chunk; + data_size -= chunk; + if (m_Pending == NPT_BASIC_DIGEST_BLOCK_SIZE) { + CompressBlock(m_Buffer); + m_Length += 8 * NPT_BASIC_DIGEST_BLOCK_SIZE; + m_Pending = 0; + } + } + } + + return NPT_SUCCESS; +} + + +/*---------------------------------------------------------------------- +| NPT_BasicDigest::ComputeDigest ++---------------------------------------------------------------------*/ +NPT_Result +NPT_BasicDigest::ComputeDigest(NPT_UInt32* state, + NPT_Cardinal state_count, + bool big_endian, + NPT_DataBuffer& digest) +{ + // increase the length of the message + m_Length += m_Pending * 8; + + // append the '1' bit + m_Buffer[m_Pending++] = 0x80; + + // if there isn't enough space left for the size (8 bytes), then compress. + // then we can fall back to padding zeros and length encoding as normal. + if (m_Pending > NPT_BASIC_DIGEST_BLOCK_SIZE-8) { + while (m_Pending < NPT_BASIC_DIGEST_BLOCK_SIZE) { + m_Buffer[m_Pending++] = 0; + } + CompressBlock(m_Buffer); + m_Pending = 0; + } + + // pad with zeroes up until the length + while (m_Pending < NPT_BASIC_DIGEST_BLOCK_SIZE-8) { + m_Buffer[m_Pending++] = 0; + } + + // store length + if (big_endian) { + NPT_BytesFromInt64Be(&m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE-8], m_Length); + } else { + NPT_BytesFromInt64Le(&m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE-8], m_Length); + } + CompressBlock(m_Buffer); + + // copy output + digest.SetDataSize(4*state_count); + NPT_UInt8* out = digest.UseData(); + if (big_endian) { + for (unsigned int i = 0; i < state_count; i++) { + NPT_BytesFromInt32Be(out, state[i]); + out += 4; + } + } else { + for (unsigned int i = 0; i < state_count; i++) { + NPT_BytesFromInt32Le(out, state[i]); + out += 4; + } + } + return NPT_SUCCESS; +} + +/*---------------------------------------------------------------------- +| NPT_Sha1Digest ++---------------------------------------------------------------------*/ +class NPT_Sha1Digest : public NPT_BasicDigest +{ +public: + NPT_Sha1Digest(); + + // NPT_Digest methods + virtual NPT_Result GetDigest(NPT_DataBuffer& digest); + virtual unsigned int GetSize() { return 20; } + +private: + // methods + virtual void CompressBlock(const NPT_UInt8* block); + + // members + NPT_UInt32 m_State[5]; +}; + +/*---------------------------------------------------------------------- +| NPT_Sha1Digest::NPT_Sha1Digest ++---------------------------------------------------------------------*/ +NPT_Sha1Digest::NPT_Sha1Digest() +{ + m_State[0] = 0x67452301UL; + m_State[1] = 0xefcdab89UL; + m_State[2] = 0x98badcfeUL; + m_State[3] = 0x10325476UL; + m_State[4] = 0xc3d2e1f0UL; +} + +/*---------------------------------------------------------------------- +| NPT_Sha1Digest::CompressBlock ++---------------------------------------------------------------------*/ +void +NPT_Sha1Digest::CompressBlock(const NPT_UInt8* block) +{ + NPT_UInt32 a,b,c,d,e,t,W[80]; + + // copy the 512-bit block into W[0..15] + for (unsigned int i = 0; i < 16; i++) { + W[i] = NPT_BytesToInt32Be(&block[4*i]); + } + + // copy the state to local variables + a = m_State[0]; + b = m_State[1]; + c = m_State[2]; + d = m_State[3]; + e = m_State[4]; + + // expand it + unsigned int i; + for (i = 16; i < 80; i++) { + W[i] = NPT_Digest_ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1); + } + + // compress + for (i = 0; i < 20; ) { + NPT_Sha1_FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; ) { + NPT_Sha1_FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; ) { + NPT_Sha1_FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; ) { + NPT_Sha1_FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t; + } + + // store the variables back into the state + m_State[0] += a; + m_State[1] += b; + m_State[2] += c; + m_State[3] += d; + m_State[4] += e; +} + +/*---------------------------------------------------------------------- +| NPT_Sha1Digest::GetDigest ++---------------------------------------------------------------------*/ +NPT_Result +NPT_Sha1Digest::GetDigest(NPT_DataBuffer& digest) +{ + return ComputeDigest(m_State, 5, true, digest); +} + +/*---------------------------------------------------------------------- +| constants ++---------------------------------------------------------------------*/ +static const NPT_UInt32 NPT_Sha256_K[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 +}; + +/*---------------------------------------------------------------------- +| NPT_Sha256Digest ++---------------------------------------------------------------------*/ +class NPT_Sha256Digest : public NPT_BasicDigest +{ +public: + NPT_Sha256Digest(); + + // NPT_Digest methods + virtual NPT_Result GetDigest(NPT_DataBuffer& digest); + virtual unsigned int GetSize() { return 32; } + +private: + // methods + virtual void CompressBlock(const NPT_UInt8* block); + + // members + NPT_UInt32 m_State[8]; +}; + +/*---------------------------------------------------------------------- +| NPT_Sha256Digest::NPT_Sha256Digest ++---------------------------------------------------------------------*/ +NPT_Sha256Digest::NPT_Sha256Digest() +{ + m_State[0] = 0x6A09E667UL; + m_State[1] = 0xBB67AE85UL; + m_State[2] = 0x3C6EF372UL; + m_State[3] = 0xA54FF53AUL; + m_State[4] = 0x510E527FUL; + m_State[5] = 0x9B05688CUL; + m_State[6] = 0x1F83D9ABUL; + m_State[7] = 0x5BE0CD19UL; +} + +/*---------------------------------------------------------------------- +| NPT_Sha256Digest::CompressBlock ++---------------------------------------------------------------------*/ +void +NPT_Sha256Digest::CompressBlock(const NPT_UInt8* block) +{ + NPT_UInt32 S[8], W[64]; + + // copy the state into the local workspace + for (unsigned int i = 0; i < 8; i++) { + S[i] = m_State[i]; + } + + // copy the 512-bit block into W[0..15] + for (unsigned int i = 0; i < 16; i++) { + W[i] = NPT_BytesToInt32Be(&block[4*i]); + } + + // fill W[16..63] + for (unsigned int i = 16; i < 64; i++) { + W[i] = NPT_Sha256_Gamma1(W[i - 2]) + W[i - 7] + NPT_Sha256_Gamma0(W[i - 15]) + W[i - 16]; + } + + // compress + for (unsigned int i = 0; i < 64; ++i) { + NPT_UInt32 t0 = + S[7] + + NPT_Sha256_Sigma1(S[4]) + + NPT_Sha256_Ch(S[4], S[5], S[6]) + + NPT_Sha256_K[i] + + W[i]; + NPT_UInt32 t1 = NPT_Sha256_Sigma0(S[0]) + NPT_Sha256_Maj(S[0], S[1], S[2]); + S[3] += t0; + S[7] = t0 + t1; + + NPT_UInt32 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4]; + S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t; + } + + // store the local variables back into the state + for (unsigned i = 0; i < 8; i++) { + m_State[i] += S[i]; + } +} + +/*---------------------------------------------------------------------- +| NPT_Sha256Digest::GetDigest ++---------------------------------------------------------------------*/ +NPT_Result +NPT_Sha256Digest::GetDigest(NPT_DataBuffer& digest) +{ + return ComputeDigest(m_State, 8, true, digest); +} + +/*---------------------------------------------------------------------- +| NPT_Md5Digest ++---------------------------------------------------------------------*/ +class NPT_Md5Digest : public NPT_BasicDigest +{ +public: + NPT_Md5Digest(); + + // NPT_Digest methods + virtual NPT_Result GetDigest(NPT_DataBuffer& digest); + virtual unsigned int GetSize() { return 16; } + +protected: + // methods + virtual void CompressBlock(const NPT_UInt8* block); + + // members + NPT_UInt32 m_State[4]; +}; + +/*---------------------------------------------------------------------- +| NPT_Md5Digest::NPT_Md5Digest ++---------------------------------------------------------------------*/ +NPT_Md5Digest::NPT_Md5Digest() +{ + m_State[0] = 0x67452301UL; + m_State[1] = 0xefcdab89UL; + m_State[2] = 0x98badcfeUL; + m_State[3] = 0x10325476UL; +} + +/*---------------------------------------------------------------------- +| NPT_Md5Digest::CompressBlock ++---------------------------------------------------------------------*/ +void +NPT_Md5Digest::CompressBlock(const NPT_UInt8* block) +{ + NPT_UInt32 a,b,c,d,W[16]; + + // copy the 512-bit block into W[0..15] + unsigned int i; + for (i = 0; i < 16; i++) { + W[i] = NPT_BytesToInt32Le(&block[4*i]); + } + + // copy the state to local variables + a = m_State[0]; + b = m_State[1]; + c = m_State[2]; + d = m_State[3]; + + // round 1 + NPT_Md5_FF(a,b,c,d,W[ 0], 7,0xd76aa478UL) + NPT_Md5_FF(d,a,b,c,W[ 1],12,0xe8c7b756UL) + NPT_Md5_FF(c,d,a,b,W[ 2],17,0x242070dbUL) + NPT_Md5_FF(b,c,d,a,W[ 3],22,0xc1bdceeeUL) + NPT_Md5_FF(a,b,c,d,W[ 4], 7,0xf57c0fafUL) + NPT_Md5_FF(d,a,b,c,W[ 5],12,0x4787c62aUL) + NPT_Md5_FF(c,d,a,b,W[ 6],17,0xa8304613UL) + NPT_Md5_FF(b,c,d,a,W[ 7],22,0xfd469501UL) + NPT_Md5_FF(a,b,c,d,W[ 8], 7,0x698098d8UL) + NPT_Md5_FF(d,a,b,c,W[ 9],12,0x8b44f7afUL) + NPT_Md5_FF(c,d,a,b,W[10],17,0xffff5bb1UL) + NPT_Md5_FF(b,c,d,a,W[11],22,0x895cd7beUL) + NPT_Md5_FF(a,b,c,d,W[12], 7,0x6b901122UL) + NPT_Md5_FF(d,a,b,c,W[13],12,0xfd987193UL) + NPT_Md5_FF(c,d,a,b,W[14],17,0xa679438eUL) + NPT_Md5_FF(b,c,d,a,W[15],22,0x49b40821UL) + + // round 2 + NPT_Md5_GG(a,b,c,d,W[ 1], 5,0xf61e2562UL) + NPT_Md5_GG(d,a,b,c,W[ 6], 9,0xc040b340UL) + NPT_Md5_GG(c,d,a,b,W[11],14,0x265e5a51UL) + NPT_Md5_GG(b,c,d,a,W[ 0],20,0xe9b6c7aaUL) + NPT_Md5_GG(a,b,c,d,W[ 5], 5,0xd62f105dUL) + NPT_Md5_GG(d,a,b,c,W[10], 9,0x02441453UL) + NPT_Md5_GG(c,d,a,b,W[15],14,0xd8a1e681UL) + NPT_Md5_GG(b,c,d,a,W[ 4],20,0xe7d3fbc8UL) + NPT_Md5_GG(a,b,c,d,W[ 9], 5,0x21e1cde6UL) + NPT_Md5_GG(d,a,b,c,W[14], 9,0xc33707d6UL) + NPT_Md5_GG(c,d,a,b,W[ 3],14,0xf4d50d87UL) + NPT_Md5_GG(b,c,d,a,W[ 8],20,0x455a14edUL) + NPT_Md5_GG(a,b,c,d,W[13], 5,0xa9e3e905UL) + NPT_Md5_GG(d,a,b,c,W[ 2], 9,0xfcefa3f8UL) + NPT_Md5_GG(c,d,a,b,W[ 7],14,0x676f02d9UL) + NPT_Md5_GG(b,c,d,a,W[12],20,0x8d2a4c8aUL) + + // round 3 + NPT_Md5_HH(a,b,c,d,W[ 5], 4,0xfffa3942UL) + NPT_Md5_HH(d,a,b,c,W[ 8],11,0x8771f681UL) + NPT_Md5_HH(c,d,a,b,W[11],16,0x6d9d6122UL) + NPT_Md5_HH(b,c,d,a,W[14],23,0xfde5380cUL) + NPT_Md5_HH(a,b,c,d,W[ 1], 4,0xa4beea44UL) + NPT_Md5_HH(d,a,b,c,W[ 4],11,0x4bdecfa9UL) + NPT_Md5_HH(c,d,a,b,W[ 7],16,0xf6bb4b60UL) + NPT_Md5_HH(b,c,d,a,W[10],23,0xbebfbc70UL) + NPT_Md5_HH(a,b,c,d,W[13], 4,0x289b7ec6UL) + NPT_Md5_HH(d,a,b,c,W[ 0],11,0xeaa127faUL) + NPT_Md5_HH(c,d,a,b,W[ 3],16,0xd4ef3085UL) + NPT_Md5_HH(b,c,d,a,W[ 6],23,0x04881d05UL) + NPT_Md5_HH(a,b,c,d,W[ 9], 4,0xd9d4d039UL) + NPT_Md5_HH(d,a,b,c,W[12],11,0xe6db99e5UL) + NPT_Md5_HH(c,d,a,b,W[15],16,0x1fa27cf8UL) + NPT_Md5_HH(b,c,d,a,W[ 2],23,0xc4ac5665UL) + + // round 4 + NPT_Md5_II(a,b,c,d,W[ 0], 6,0xf4292244UL) + NPT_Md5_II(d,a,b,c,W[ 7],10,0x432aff97UL) + NPT_Md5_II(c,d,a,b,W[14],15,0xab9423a7UL) + NPT_Md5_II(b,c,d,a,W[ 5],21,0xfc93a039UL) + NPT_Md5_II(a,b,c,d,W[12], 6,0x655b59c3UL) + NPT_Md5_II(d,a,b,c,W[ 3],10,0x8f0ccc92UL) + NPT_Md5_II(c,d,a,b,W[10],15,0xffeff47dUL) + NPT_Md5_II(b,c,d,a,W[ 1],21,0x85845dd1UL) + NPT_Md5_II(a,b,c,d,W[ 8], 6,0x6fa87e4fUL) + NPT_Md5_II(d,a,b,c,W[15],10,0xfe2ce6e0UL) + NPT_Md5_II(c,d,a,b,W[ 6],15,0xa3014314UL) + NPT_Md5_II(b,c,d,a,W[13],21,0x4e0811a1UL) + NPT_Md5_II(a,b,c,d,W[ 4], 6,0xf7537e82UL) + NPT_Md5_II(d,a,b,c,W[11],10,0xbd3af235UL) + NPT_Md5_II(c,d,a,b,W[ 2],15,0x2ad7d2bbUL) + NPT_Md5_II(b,c,d,a,W[ 9],21,0xeb86d391UL) + + // store the variables back into the state + m_State[0] += a; + m_State[1] += b; + m_State[2] += c; + m_State[3] += d; +} + +/*---------------------------------------------------------------------- +| NPT_Md5Digest::GetDigest ++---------------------------------------------------------------------*/ +NPT_Result +NPT_Md5Digest::GetDigest(NPT_DataBuffer& digest) +{ + return ComputeDigest(m_State, 4, false, digest); +} + +/*---------------------------------------------------------------------- +| NPT_HmacDigest +| +| compute Digest(key XOR opad, Digest(key XOR ipad, data)) +| key is the MAC key +| ipad is the byte 0x36 repeated 64 times +| opad is the byte 0x5c repeated 64 times +| and data is the data to authenticate +| ++---------------------------------------------------------------------*/ +class NPT_HmacDigest : public NPT_Digest +{ +public: + NPT_HmacDigest(NPT_Digest::Algorithm algorithm, + const NPT_UInt8* key, + NPT_Size key_size); + ~NPT_HmacDigest(); + + // NPT_Digest methods + virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size) { + return m_InnerDigest->Update(data, data_size); + } + virtual NPT_Result GetDigest(NPT_DataBuffer& buffer); + virtual unsigned int GetSize() { return m_InnerDigest->GetSize(); } + +private: + NPT_Digest* m_InnerDigest; + NPT_Digest* m_OuterDigest; +}; + +/*---------------------------------------------------------------------- +| NPT_HmacDigest::NPT_HmacDigest ++---------------------------------------------------------------------*/ +NPT_HmacDigest::NPT_HmacDigest(NPT_Digest::Algorithm algorithm, + const NPT_UInt8* key, + NPT_Size key_size) +{ + NPT_Digest::Create(algorithm, m_InnerDigest); + NPT_Digest::Create(algorithm, m_OuterDigest); + + NPT_UInt8 workspace[NPT_BASIC_DIGEST_BLOCK_SIZE]; + + // if the key is larger than the block size, use a digest of the key + NPT_DataBuffer hk; + if (key_size > NPT_BASIC_DIGEST_BLOCK_SIZE) { + NPT_Digest* key_digest = NULL; + NPT_Digest::Create(algorithm, key_digest); + key_digest->Update(key, key_size); + key_digest->GetDigest(hk); + key = hk.GetData(); + key_size = hk.GetDataSize(); + delete key_digest; + } + + // compute key XOR ipad + for (unsigned int i = 0; i < key_size; i++) { + workspace[i] = key[i] ^ 0x36; + } + for (unsigned int i = key_size; i < NPT_BASIC_DIGEST_BLOCK_SIZE; i++) { + workspace[i] = 0x36; + } + + // start the inner digest with (key XOR ipad) + m_InnerDigest->Update(workspace, NPT_BASIC_DIGEST_BLOCK_SIZE); + + // compute key XOR opad + for (unsigned int i = 0; i < key_size; i++) { + workspace[i] = key[i] ^ 0x5c; + } + for (unsigned int i = key_size; i < NPT_BASIC_DIGEST_BLOCK_SIZE; i++) { + workspace[i] = 0x5c; + } + + // start the outer digest with (key XOR opad) + m_OuterDigest->Update(workspace, NPT_BASIC_DIGEST_BLOCK_SIZE); +} + +/*---------------------------------------------------------------------- +| NPT_HmacDigest::~NPT_HmacDigest ++---------------------------------------------------------------------*/ +NPT_HmacDigest::~NPT_HmacDigest() +{ + delete m_InnerDigest; + delete m_OuterDigest; +} + +/*---------------------------------------------------------------------- +| NPT_HmacDigest::GetDigest ++---------------------------------------------------------------------*/ +NPT_Result +NPT_HmacDigest::GetDigest(NPT_DataBuffer& mac) +{ + // finish the outer digest with the value of the inner digest + NPT_DataBuffer inner; + m_InnerDigest->GetDigest(inner); + m_OuterDigest->Update(inner.GetData(), inner.GetDataSize()); + + // return the value of the outer digest + return m_OuterDigest->GetDigest(mac); +} + +/*---------------------------------------------------------------------- +| NPT_Digest::Create ++---------------------------------------------------------------------*/ +NPT_Result +NPT_Digest::Create(Algorithm algorithm, NPT_Digest*& digest) +{ + switch (algorithm) { + case ALGORITHM_SHA1: digest = new NPT_Sha1Digest(); return NPT_SUCCESS; + case ALGORITHM_SHA256: digest = new NPT_Sha256Digest(); return NPT_SUCCESS; + case ALGORITHM_MD5: digest = new NPT_Md5Digest(); return NPT_SUCCESS; + default: return NPT_ERROR_NOT_SUPPORTED; + } +} + +/*---------------------------------------------------------------------- +| NPT_Hmac::Create ++---------------------------------------------------------------------*/ +NPT_Result +NPT_Hmac::Create(NPT_Digest::Algorithm algorithm, + const NPT_UInt8* key, + NPT_Size key_size, + NPT_Digest*& digest) +{ + switch (algorithm) { + case NPT_Digest::ALGORITHM_SHA1: + case NPT_Digest::ALGORITHM_MD5: + digest = new NPT_HmacDigest(algorithm, key, key_size); + return NPT_SUCCESS; + default: return NPT_ERROR_NOT_SUPPORTED; + } +} |