summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/Neptune/Source/Core/NptDigest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/Neptune/Source/Core/NptDigest.cpp')
-rw-r--r--lib/libUPnP/Neptune/Source/Core/NptDigest.cpp685
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;
+ }
+}