Merge pull request #25959 from neo1973/TagLib_deprecation_warnings
[xbmc.git] / lib / libUPnP / Neptune / Source / Core / NptDigest.cpp
blob4e7fb748c526c508ea758a5cfdd62830f7aca2e0
1 /*****************************************************************
3 | Neptune - Message Digests
5 | Copyright (c) 2002-2010, Axiomatic Systems, LLC.
6 | All rights reserved.
8 | Redistribution and use in source and binary forms, with or without
9 | modification, are permitted provided that the following conditions are met:
10 | * Redistributions of source code must retain the above copyright
11 | notice, this list of conditions and the following disclaimer.
12 | * Redistributions in binary form must reproduce the above copyright
13 | notice, this list of conditions and the following disclaimer in the
14 | documentation and/or other materials provided with the distribution.
15 | * Neither the name of Axiomatic Systems nor the
16 | names of its contributors may be used to endorse or promote products
17 | derived from this software without specific prior written permission.
19 | THIS SOFTWARE IS PROVIDED BY AXIOMATIC SYSTEMS ''AS IS'' AND ANY
20 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 | DISCLAIMED. IN NO EVENT SHALL AXIOMATIC SYSTEMS BE LIABLE FOR ANY
23 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 ****************************************************************/
33 Portions of this code are based on the code of LibTomCrypt
34 that was released into public domain by Tom St Denis.
37 /*----------------------------------------------------------------------
38 | includes
39 +---------------------------------------------------------------------*/
40 #include "NptDigest.h"
41 #include "NptUtils.h"
43 /*----------------------------------------------------------------------
44 | constants
45 +---------------------------------------------------------------------*/
46 #define NPT_BASIC_DIGEST_BLOCK_SIZE 64
48 /*----------------------------------------------------------------------
49 | macros
50 +---------------------------------------------------------------------*/
51 #define NPT_Digest_ROL(x, y) \
52 ( (((NPT_UInt32)(x) << (y)) | (((NPT_UInt32)(x) & 0xFFFFFFFFUL) >> (32 - (y)))) & 0xFFFFFFFFUL)
53 #define NPT_Digest_ROR(x, y) \
54 ( ((((NPT_UInt32)(x)&0xFFFFFFFFUL)>>(NPT_UInt32)((y)&31)) | ((NPT_UInt32)(x)<<(NPT_UInt32)(32-((y)&31)))) & 0xFFFFFFFFUL)
56 #define NPT_Sha1_F0(x,y,z) (z ^ (x & (y ^ z)))
57 #define NPT_Sha1_F1(x,y,z) (x ^ y ^ z)
58 #define NPT_Sha1_F2(x,y,z) ((x & y) | (z & (x | y)))
59 #define NPT_Sha1_F3(x,y,z) (x ^ y ^ z)
61 #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);
62 #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);
63 #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);
64 #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);
66 #define NPT_Sha256_Ch(x,y,z) (z ^ (x & (y ^ z)))
67 #define NPT_Sha256_Maj(x,y,z) (((x | y) & z) | (x & y))
68 #define NPT_Sha256_S(x, n) NPT_Digest_ROR((x),(n))
69 #define NPT_Sha256_R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
70 #define NPT_Sha256_Sigma0(x) (NPT_Sha256_S(x, 2) ^ NPT_Sha256_S(x, 13) ^ NPT_Sha256_S(x, 22))
71 #define NPT_Sha256_Sigma1(x) (NPT_Sha256_S(x, 6) ^ NPT_Sha256_S(x, 11) ^ NPT_Sha256_S(x, 25))
72 #define NPT_Sha256_Gamma0(x) (NPT_Sha256_S(x, 7) ^ NPT_Sha256_S(x, 18) ^ NPT_Sha256_R(x, 3))
73 #define NPT_Sha256_Gamma1(x) (NPT_Sha256_S(x, 17) ^ NPT_Sha256_S(x, 19) ^ NPT_Sha256_R(x, 10))
76 #define NPT_Md5_F(x,y,z) (z ^ (x & (y ^ z)))
77 #define NPT_Md5_G(x,y,z) (y ^ (z & (y ^ x)))
78 #define NPT_Md5_H(x,y,z) (x ^ y ^ z)
79 #define NPT_Md5_I(x,y,z) (y ^ (x | (~z)))
81 #define NPT_Md5_FF(a,b,c,d,M,s,t) \
82 a = (a + NPT_Md5_F(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
84 #define NPT_Md5_GG(a,b,c,d,M,s,t) \
85 a = (a + NPT_Md5_G(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
87 #define NPT_Md5_HH(a,b,c,d,M,s,t) \
88 a = (a + NPT_Md5_H(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
90 #define NPT_Md5_II(a,b,c,d,M,s,t) \
91 a = (a + NPT_Md5_I(b,c,d) + M + t); a = NPT_Digest_ROL(a, s) + b;
93 /*----------------------------------------------------------------------
94 | NPT_BasicDigest
95 +---------------------------------------------------------------------*/
96 class NPT_BasicDigest : public NPT_Digest
98 public:
99 NPT_BasicDigest();
101 // NPT_Digest methods
102 virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size);
104 protected:
105 // methods
106 NPT_Result ComputeDigest(NPT_UInt32* state,
107 NPT_Cardinal state_count,
108 bool big_endian,
109 NPT_DataBuffer& digest);
110 virtual void CompressBlock(const NPT_UInt8* block) = 0;
112 // members
113 NPT_UInt64 m_Length;
114 NPT_UInt32 m_Pending;
115 NPT_UInt8 m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE];
118 /*----------------------------------------------------------------------
119 | NPT_BasicDigest::NPT_BasicDigest
120 +---------------------------------------------------------------------*/
121 NPT_BasicDigest::NPT_BasicDigest() :
122 m_Length(0),
123 m_Pending(0)
127 /*----------------------------------------------------------------------
128 | NPT_BasicDigest::Update
129 +---------------------------------------------------------------------*/
130 NPT_Result
131 NPT_BasicDigest::Update(const NPT_UInt8* data, NPT_Size data_size)
133 while (data_size > 0) {
134 if (m_Pending == 0 && data_size >= NPT_BASIC_DIGEST_BLOCK_SIZE) {
135 CompressBlock(data);
136 m_Length += NPT_BASIC_DIGEST_BLOCK_SIZE * 8;
137 data += NPT_BASIC_DIGEST_BLOCK_SIZE;
138 data_size -= NPT_BASIC_DIGEST_BLOCK_SIZE;
139 } else {
140 unsigned int chunk = data_size;
141 if (chunk > (NPT_BASIC_DIGEST_BLOCK_SIZE - m_Pending)) {
142 chunk = NPT_BASIC_DIGEST_BLOCK_SIZE - m_Pending;
144 NPT_CopyMemory(&m_Buffer[m_Pending], data, chunk);
145 m_Pending += chunk;
146 data += chunk;
147 data_size -= chunk;
148 if (m_Pending == NPT_BASIC_DIGEST_BLOCK_SIZE) {
149 CompressBlock(m_Buffer);
150 m_Length += 8 * NPT_BASIC_DIGEST_BLOCK_SIZE;
151 m_Pending = 0;
156 return NPT_SUCCESS;
160 /*----------------------------------------------------------------------
161 | NPT_BasicDigest::ComputeDigest
162 +---------------------------------------------------------------------*/
163 NPT_Result
164 NPT_BasicDigest::ComputeDigest(NPT_UInt32* state,
165 NPT_Cardinal state_count,
166 bool big_endian,
167 NPT_DataBuffer& digest)
169 // increase the length of the message
170 m_Length += m_Pending * 8;
172 // append the '1' bit
173 m_Buffer[m_Pending++] = 0x80;
175 // if there isn't enough space left for the size (8 bytes), then compress.
176 // then we can fall back to padding zeros and length encoding as normal.
177 if (m_Pending > NPT_BASIC_DIGEST_BLOCK_SIZE-8) {
178 while (m_Pending < NPT_BASIC_DIGEST_BLOCK_SIZE) {
179 m_Buffer[m_Pending++] = 0;
181 CompressBlock(m_Buffer);
182 m_Pending = 0;
185 // pad with zeroes up until the length
186 while (m_Pending < NPT_BASIC_DIGEST_BLOCK_SIZE-8) {
187 m_Buffer[m_Pending++] = 0;
190 // store length
191 if (big_endian) {
192 NPT_BytesFromInt64Be(&m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE-8], m_Length);
193 } else {
194 NPT_BytesFromInt64Le(&m_Buffer[NPT_BASIC_DIGEST_BLOCK_SIZE-8], m_Length);
196 CompressBlock(m_Buffer);
198 // copy output
199 digest.SetDataSize(4*state_count);
200 NPT_UInt8* out = digest.UseData();
201 if (big_endian) {
202 for (unsigned int i = 0; i < state_count; i++) {
203 NPT_BytesFromInt32Be(out, state[i]);
204 out += 4;
206 } else {
207 for (unsigned int i = 0; i < state_count; i++) {
208 NPT_BytesFromInt32Le(out, state[i]);
209 out += 4;
212 return NPT_SUCCESS;
215 /*----------------------------------------------------------------------
216 | NPT_Sha1Digest
217 +---------------------------------------------------------------------*/
218 class NPT_Sha1Digest : public NPT_BasicDigest
220 public:
221 NPT_Sha1Digest();
223 // NPT_Digest methods
224 virtual NPT_Result GetDigest(NPT_DataBuffer& digest);
225 virtual unsigned int GetSize() { return 20; }
227 private:
228 // methods
229 virtual void CompressBlock(const NPT_UInt8* block);
231 // members
232 NPT_UInt32 m_State[5];
235 /*----------------------------------------------------------------------
236 | NPT_Sha1Digest::NPT_Sha1Digest
237 +---------------------------------------------------------------------*/
238 NPT_Sha1Digest::NPT_Sha1Digest()
240 m_State[0] = 0x67452301UL;
241 m_State[1] = 0xefcdab89UL;
242 m_State[2] = 0x98badcfeUL;
243 m_State[3] = 0x10325476UL;
244 m_State[4] = 0xc3d2e1f0UL;
247 /*----------------------------------------------------------------------
248 | NPT_Sha1Digest::CompressBlock
249 +---------------------------------------------------------------------*/
250 void
251 NPT_Sha1Digest::CompressBlock(const NPT_UInt8* block)
253 NPT_UInt32 a,b,c,d,e,t,W[80];
255 // copy the 512-bit block into W[0..15]
256 for (unsigned int i = 0; i < 16; i++) {
257 W[i] = NPT_BytesToInt32Be(&block[4*i]);
260 // copy the state to local variables
261 a = m_State[0];
262 b = m_State[1];
263 c = m_State[2];
264 d = m_State[3];
265 e = m_State[4];
267 // expand it
268 unsigned int i;
269 for (i = 16; i < 80; i++) {
270 W[i] = NPT_Digest_ROL(W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16], 1);
273 // compress
274 for (i = 0; i < 20; ) {
275 NPT_Sha1_FF0(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
278 for (; i < 40; ) {
279 NPT_Sha1_FF1(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
282 for (; i < 60; ) {
283 NPT_Sha1_FF2(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
286 for (; i < 80; ) {
287 NPT_Sha1_FF3(a,b,c,d,e,i++); t = e; e = d; d = c; c = b; b = a; a = t;
290 // store the variables back into the state
291 m_State[0] += a;
292 m_State[1] += b;
293 m_State[2] += c;
294 m_State[3] += d;
295 m_State[4] += e;
298 /*----------------------------------------------------------------------
299 | NPT_Sha1Digest::GetDigest
300 +---------------------------------------------------------------------*/
301 NPT_Result
302 NPT_Sha1Digest::GetDigest(NPT_DataBuffer& digest)
304 return ComputeDigest(m_State, 5, true, digest);
307 /*----------------------------------------------------------------------
308 | constants
309 +---------------------------------------------------------------------*/
310 static const NPT_UInt32 NPT_Sha256_K[64] = {
311 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
312 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
313 0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
314 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
315 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
316 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
317 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
318 0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
319 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
320 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
321 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
322 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
323 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
326 /*----------------------------------------------------------------------
327 | NPT_Sha256Digest
328 +---------------------------------------------------------------------*/
329 class NPT_Sha256Digest : public NPT_BasicDigest
331 public:
332 NPT_Sha256Digest();
334 // NPT_Digest methods
335 virtual NPT_Result GetDigest(NPT_DataBuffer& digest);
336 virtual unsigned int GetSize() { return 32; }
338 private:
339 // methods
340 virtual void CompressBlock(const NPT_UInt8* block);
342 // members
343 NPT_UInt32 m_State[8];
346 /*----------------------------------------------------------------------
347 | NPT_Sha256Digest::NPT_Sha256Digest
348 +---------------------------------------------------------------------*/
349 NPT_Sha256Digest::NPT_Sha256Digest()
351 m_State[0] = 0x6A09E667UL;
352 m_State[1] = 0xBB67AE85UL;
353 m_State[2] = 0x3C6EF372UL;
354 m_State[3] = 0xA54FF53AUL;
355 m_State[4] = 0x510E527FUL;
356 m_State[5] = 0x9B05688CUL;
357 m_State[6] = 0x1F83D9ABUL;
358 m_State[7] = 0x5BE0CD19UL;
361 /*----------------------------------------------------------------------
362 | NPT_Sha256Digest::CompressBlock
363 +---------------------------------------------------------------------*/
364 void
365 NPT_Sha256Digest::CompressBlock(const NPT_UInt8* block)
367 NPT_UInt32 S[8], W[64];
369 // copy the state into the local workspace
370 for (unsigned int i = 0; i < 8; i++) {
371 S[i] = m_State[i];
374 // copy the 512-bit block into W[0..15]
375 for (unsigned int i = 0; i < 16; i++) {
376 W[i] = NPT_BytesToInt32Be(&block[4*i]);
379 // fill W[16..63]
380 for (unsigned int i = 16; i < 64; i++) {
381 W[i] = NPT_Sha256_Gamma1(W[i - 2]) + W[i - 7] + NPT_Sha256_Gamma0(W[i - 15]) + W[i - 16];
384 // compress
385 for (unsigned int i = 0; i < 64; ++i) {
386 NPT_UInt32 t0 =
387 S[7] +
388 NPT_Sha256_Sigma1(S[4]) +
389 NPT_Sha256_Ch(S[4], S[5], S[6]) +
390 NPT_Sha256_K[i] +
391 W[i];
392 NPT_UInt32 t1 = NPT_Sha256_Sigma0(S[0]) + NPT_Sha256_Maj(S[0], S[1], S[2]);
393 S[3] += t0;
394 S[7] = t0 + t1;
396 NPT_UInt32 t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
397 S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
400 // store the local variables back into the state
401 for (unsigned i = 0; i < 8; i++) {
402 m_State[i] += S[i];
406 /*----------------------------------------------------------------------
407 | NPT_Sha256Digest::GetDigest
408 +---------------------------------------------------------------------*/
409 NPT_Result
410 NPT_Sha256Digest::GetDigest(NPT_DataBuffer& digest)
412 return ComputeDigest(m_State, 8, true, digest);
415 /*----------------------------------------------------------------------
416 | NPT_Md5Digest
417 +---------------------------------------------------------------------*/
418 class NPT_Md5Digest : public NPT_BasicDigest
420 public:
421 NPT_Md5Digest();
423 // NPT_Digest methods
424 virtual NPT_Result GetDigest(NPT_DataBuffer& digest);
425 virtual unsigned int GetSize() { return 16; }
427 protected:
428 // methods
429 virtual void CompressBlock(const NPT_UInt8* block);
431 // members
432 NPT_UInt32 m_State[4];
435 /*----------------------------------------------------------------------
436 | NPT_Md5Digest::NPT_Md5Digest
437 +---------------------------------------------------------------------*/
438 NPT_Md5Digest::NPT_Md5Digest()
440 m_State[0] = 0x67452301UL;
441 m_State[1] = 0xefcdab89UL;
442 m_State[2] = 0x98badcfeUL;
443 m_State[3] = 0x10325476UL;
446 /*----------------------------------------------------------------------
447 | NPT_Md5Digest::CompressBlock
448 +---------------------------------------------------------------------*/
449 void
450 NPT_Md5Digest::CompressBlock(const NPT_UInt8* block)
452 NPT_UInt32 a,b,c,d,W[16];
454 // copy the 512-bit block into W[0..15]
455 unsigned int i;
456 for (i = 0; i < 16; i++) {
457 W[i] = NPT_BytesToInt32Le(&block[4*i]);
460 // copy the state to local variables
461 a = m_State[0];
462 b = m_State[1];
463 c = m_State[2];
464 d = m_State[3];
466 // round 1
467 NPT_Md5_FF(a,b,c,d,W[ 0], 7,0xd76aa478UL)
468 NPT_Md5_FF(d,a,b,c,W[ 1],12,0xe8c7b756UL)
469 NPT_Md5_FF(c,d,a,b,W[ 2],17,0x242070dbUL)
470 NPT_Md5_FF(b,c,d,a,W[ 3],22,0xc1bdceeeUL)
471 NPT_Md5_FF(a,b,c,d,W[ 4], 7,0xf57c0fafUL)
472 NPT_Md5_FF(d,a,b,c,W[ 5],12,0x4787c62aUL)
473 NPT_Md5_FF(c,d,a,b,W[ 6],17,0xa8304613UL)
474 NPT_Md5_FF(b,c,d,a,W[ 7],22,0xfd469501UL)
475 NPT_Md5_FF(a,b,c,d,W[ 8], 7,0x698098d8UL)
476 NPT_Md5_FF(d,a,b,c,W[ 9],12,0x8b44f7afUL)
477 NPT_Md5_FF(c,d,a,b,W[10],17,0xffff5bb1UL)
478 NPT_Md5_FF(b,c,d,a,W[11],22,0x895cd7beUL)
479 NPT_Md5_FF(a,b,c,d,W[12], 7,0x6b901122UL)
480 NPT_Md5_FF(d,a,b,c,W[13],12,0xfd987193UL)
481 NPT_Md5_FF(c,d,a,b,W[14],17,0xa679438eUL)
482 NPT_Md5_FF(b,c,d,a,W[15],22,0x49b40821UL)
484 // round 2
485 NPT_Md5_GG(a,b,c,d,W[ 1], 5,0xf61e2562UL)
486 NPT_Md5_GG(d,a,b,c,W[ 6], 9,0xc040b340UL)
487 NPT_Md5_GG(c,d,a,b,W[11],14,0x265e5a51UL)
488 NPT_Md5_GG(b,c,d,a,W[ 0],20,0xe9b6c7aaUL)
489 NPT_Md5_GG(a,b,c,d,W[ 5], 5,0xd62f105dUL)
490 NPT_Md5_GG(d,a,b,c,W[10], 9,0x02441453UL)
491 NPT_Md5_GG(c,d,a,b,W[15],14,0xd8a1e681UL)
492 NPT_Md5_GG(b,c,d,a,W[ 4],20,0xe7d3fbc8UL)
493 NPT_Md5_GG(a,b,c,d,W[ 9], 5,0x21e1cde6UL)
494 NPT_Md5_GG(d,a,b,c,W[14], 9,0xc33707d6UL)
495 NPT_Md5_GG(c,d,a,b,W[ 3],14,0xf4d50d87UL)
496 NPT_Md5_GG(b,c,d,a,W[ 8],20,0x455a14edUL)
497 NPT_Md5_GG(a,b,c,d,W[13], 5,0xa9e3e905UL)
498 NPT_Md5_GG(d,a,b,c,W[ 2], 9,0xfcefa3f8UL)
499 NPT_Md5_GG(c,d,a,b,W[ 7],14,0x676f02d9UL)
500 NPT_Md5_GG(b,c,d,a,W[12],20,0x8d2a4c8aUL)
502 // round 3
503 NPT_Md5_HH(a,b,c,d,W[ 5], 4,0xfffa3942UL)
504 NPT_Md5_HH(d,a,b,c,W[ 8],11,0x8771f681UL)
505 NPT_Md5_HH(c,d,a,b,W[11],16,0x6d9d6122UL)
506 NPT_Md5_HH(b,c,d,a,W[14],23,0xfde5380cUL)
507 NPT_Md5_HH(a,b,c,d,W[ 1], 4,0xa4beea44UL)
508 NPT_Md5_HH(d,a,b,c,W[ 4],11,0x4bdecfa9UL)
509 NPT_Md5_HH(c,d,a,b,W[ 7],16,0xf6bb4b60UL)
510 NPT_Md5_HH(b,c,d,a,W[10],23,0xbebfbc70UL)
511 NPT_Md5_HH(a,b,c,d,W[13], 4,0x289b7ec6UL)
512 NPT_Md5_HH(d,a,b,c,W[ 0],11,0xeaa127faUL)
513 NPT_Md5_HH(c,d,a,b,W[ 3],16,0xd4ef3085UL)
514 NPT_Md5_HH(b,c,d,a,W[ 6],23,0x04881d05UL)
515 NPT_Md5_HH(a,b,c,d,W[ 9], 4,0xd9d4d039UL)
516 NPT_Md5_HH(d,a,b,c,W[12],11,0xe6db99e5UL)
517 NPT_Md5_HH(c,d,a,b,W[15],16,0x1fa27cf8UL)
518 NPT_Md5_HH(b,c,d,a,W[ 2],23,0xc4ac5665UL)
520 // round 4
521 NPT_Md5_II(a,b,c,d,W[ 0], 6,0xf4292244UL)
522 NPT_Md5_II(d,a,b,c,W[ 7],10,0x432aff97UL)
523 NPT_Md5_II(c,d,a,b,W[14],15,0xab9423a7UL)
524 NPT_Md5_II(b,c,d,a,W[ 5],21,0xfc93a039UL)
525 NPT_Md5_II(a,b,c,d,W[12], 6,0x655b59c3UL)
526 NPT_Md5_II(d,a,b,c,W[ 3],10,0x8f0ccc92UL)
527 NPT_Md5_II(c,d,a,b,W[10],15,0xffeff47dUL)
528 NPT_Md5_II(b,c,d,a,W[ 1],21,0x85845dd1UL)
529 NPT_Md5_II(a,b,c,d,W[ 8], 6,0x6fa87e4fUL)
530 NPT_Md5_II(d,a,b,c,W[15],10,0xfe2ce6e0UL)
531 NPT_Md5_II(c,d,a,b,W[ 6],15,0xa3014314UL)
532 NPT_Md5_II(b,c,d,a,W[13],21,0x4e0811a1UL)
533 NPT_Md5_II(a,b,c,d,W[ 4], 6,0xf7537e82UL)
534 NPT_Md5_II(d,a,b,c,W[11],10,0xbd3af235UL)
535 NPT_Md5_II(c,d,a,b,W[ 2],15,0x2ad7d2bbUL)
536 NPT_Md5_II(b,c,d,a,W[ 9],21,0xeb86d391UL)
538 // store the variables back into the state
539 m_State[0] += a;
540 m_State[1] += b;
541 m_State[2] += c;
542 m_State[3] += d;
545 /*----------------------------------------------------------------------
546 | NPT_Md5Digest::GetDigest
547 +---------------------------------------------------------------------*/
548 NPT_Result
549 NPT_Md5Digest::GetDigest(NPT_DataBuffer& digest)
551 return ComputeDigest(m_State, 4, false, digest);
554 /*----------------------------------------------------------------------
555 | NPT_HmacDigest
557 | compute Digest(key XOR opad, Digest(key XOR ipad, data))
558 | key is the MAC key
559 | ipad is the byte 0x36 repeated 64 times
560 | opad is the byte 0x5c repeated 64 times
561 | and data is the data to authenticate
563 +---------------------------------------------------------------------*/
564 class NPT_HmacDigest : public NPT_Digest
566 public:
567 NPT_HmacDigest(NPT_Digest::Algorithm algorithm,
568 const NPT_UInt8* key,
569 NPT_Size key_size);
570 ~NPT_HmacDigest();
572 // NPT_Digest methods
573 virtual NPT_Result Update(const NPT_UInt8* data, NPT_Size data_size) {
574 return m_InnerDigest->Update(data, data_size);
576 virtual NPT_Result GetDigest(NPT_DataBuffer& buffer);
577 virtual unsigned int GetSize() { return m_InnerDigest->GetSize(); }
579 private:
580 NPT_Digest* m_InnerDigest;
581 NPT_Digest* m_OuterDigest;
584 /*----------------------------------------------------------------------
585 | NPT_HmacDigest::NPT_HmacDigest
586 +---------------------------------------------------------------------*/
587 NPT_HmacDigest::NPT_HmacDigest(NPT_Digest::Algorithm algorithm,
588 const NPT_UInt8* key,
589 NPT_Size key_size)
591 NPT_Digest::Create(algorithm, m_InnerDigest);
592 NPT_Digest::Create(algorithm, m_OuterDigest);
594 NPT_UInt8 workspace[NPT_BASIC_DIGEST_BLOCK_SIZE];
596 // if the key is larger than the block size, use a digest of the key
597 NPT_DataBuffer hk;
598 if (key_size > NPT_BASIC_DIGEST_BLOCK_SIZE) {
599 NPT_Digest* key_digest = NULL;
600 NPT_Digest::Create(algorithm, key_digest);
601 key_digest->Update(key, key_size);
602 key_digest->GetDigest(hk);
603 key = hk.GetData();
604 key_size = hk.GetDataSize();
605 delete key_digest;
608 // compute key XOR ipad
609 for (unsigned int i = 0; i < key_size; i++) {
610 workspace[i] = key[i] ^ 0x36;
612 for (unsigned int i = key_size; i < NPT_BASIC_DIGEST_BLOCK_SIZE; i++) {
613 workspace[i] = 0x36;
616 // start the inner digest with (key XOR ipad)
617 m_InnerDigest->Update(workspace, NPT_BASIC_DIGEST_BLOCK_SIZE);
619 // compute key XOR opad
620 for (unsigned int i = 0; i < key_size; i++) {
621 workspace[i] = key[i] ^ 0x5c;
623 for (unsigned int i = key_size; i < NPT_BASIC_DIGEST_BLOCK_SIZE; i++) {
624 workspace[i] = 0x5c;
627 // start the outer digest with (key XOR opad)
628 m_OuterDigest->Update(workspace, NPT_BASIC_DIGEST_BLOCK_SIZE);
631 /*----------------------------------------------------------------------
632 | NPT_HmacDigest::~NPT_HmacDigest
633 +---------------------------------------------------------------------*/
634 NPT_HmacDigest::~NPT_HmacDigest()
636 delete m_InnerDigest;
637 delete m_OuterDigest;
640 /*----------------------------------------------------------------------
641 | NPT_HmacDigest::GetDigest
642 +---------------------------------------------------------------------*/
643 NPT_Result
644 NPT_HmacDigest::GetDigest(NPT_DataBuffer& mac)
646 // finish the outer digest with the value of the inner digest
647 NPT_DataBuffer inner;
648 m_InnerDigest->GetDigest(inner);
649 m_OuterDigest->Update(inner.GetData(), inner.GetDataSize());
651 // return the value of the outer digest
652 return m_OuterDigest->GetDigest(mac);
655 /*----------------------------------------------------------------------
656 | NPT_Digest::Create
657 +---------------------------------------------------------------------*/
658 NPT_Result
659 NPT_Digest::Create(Algorithm algorithm, NPT_Digest*& digest)
661 switch (algorithm) {
662 case ALGORITHM_SHA1: digest = new NPT_Sha1Digest(); return NPT_SUCCESS;
663 case ALGORITHM_SHA256: digest = new NPT_Sha256Digest(); return NPT_SUCCESS;
664 case ALGORITHM_MD5: digest = new NPT_Md5Digest(); return NPT_SUCCESS;
665 default: return NPT_ERROR_NOT_SUPPORTED;
669 /*----------------------------------------------------------------------
670 | NPT_Hmac::Create
671 +---------------------------------------------------------------------*/
672 NPT_Result
673 NPT_Hmac::Create(NPT_Digest::Algorithm algorithm,
674 const NPT_UInt8* key,
675 NPT_Size key_size,
676 NPT_Digest*& digest)
678 switch (algorithm) {
679 case NPT_Digest::ALGORITHM_SHA1:
680 case NPT_Digest::ALGORITHM_MD5:
681 digest = new NPT_HmacDigest(algorithm, key, key_size);
682 return NPT_SUCCESS;
683 default: return NPT_ERROR_NOT_SUPPORTED;