1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MATH - libraries
3   File:     dgt_md5.c
4 
5   Copyright 2003-2008 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2008-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 
19 #include <nitro/types.h>
20 #include <nitro/mi/memory.h>
21 #include <nitro/math/dgt.h>
22 #include "hmac.h"
23 
24 #ifdef  SDK_WIN32
25 #include <string.h>
26 #define MI_CpuCopy8(_x_, _y_, _z_)  memcpy(_y_, _x_, _z_)
27 #define MI_CpuFill8                 memset
28 #endif
29 
30 /*  The ARM7 is located on LTDWRAM for the TWL SDK's WPA */
31 #ifdef SDK_TWLHYB
32 #ifdef SDK_ARM7
33 #include <twl/ltdwram_begin.h>
34 #endif
35 #endif
36 
37 //
38 // Calculate MD5 digest
39 //
40 
41 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
42 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
43 #define H(x, y, z) ((x) ^ (y) ^ (z))
44 #define I(x, y, z) ((y) ^ ((x) | (~z)))
45 #define ROTL(x, n) (((x) << (n)) | ((x) >> (32-(n))))
46 
47 static void ProcessBlock(MATHMD5Context* context);
48 
CalcRound1(u32 a,u32 b,u32 c,u32 d,u32 x,u32 s,u32 t)49 inline static u32 CalcRound1(u32 a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 t)
50 {
51     return b + ROTL((a + F(b,c,d) + x + t), s);
52 }
53 
CalcRound2(u32 a,u32 b,u32 c,u32 d,u32 x,u32 s,u32 t)54 inline static u32 CalcRound2(u32 a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 t)
55 {
56     return b + ROTL((a + G(b,c,d) + x + t), s);
57 }
58 
CalcRound3(u32 a,u32 b,u32 c,u32 d,u32 x,u32 s,u32 t)59 inline static u32 CalcRound3(u32 a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 t)
60 {
61     return b + ROTL((a + H(b,c,d) + x + t), s);
62 }
63 
CalcRound4(u32 a,u32 b,u32 c,u32 d,u32 x,u32 s,u32 t)64 inline static u32 CalcRound4(u32 a, u32 b, u32 c, u32 d, u32 x, u32 s, u32 t)
65 {
66     return b + ROTL((a + I(b,c,d) + x + t), s);
67 }
68 
ProcessBlock(MATHMD5Context * context)69 static void ProcessBlock(MATHMD5Context* context)
70 {
71     static u32 t[] =
72     {
73         0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
74         0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
75         0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
76         0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
77 #ifndef SDK_DIGEST_MD5_FAST
78         0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
79         0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
80         0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
81         0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
82         0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
83         0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
84         0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
85         0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
86         0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
87         0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
88         0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
89         0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
90 #else
91      1, 0xf61e2562,
92      6, 0xc040b340,
93     11, 0x265e5a51,
94      0, 0xe9b6c7aa,
95      5, 0xd62f105d,
96     10,  0x2441453,
97     15, 0xd8a1e681,
98      4, 0xe7d3fbc8,
99      9, 0x21e1cde6,
100     14, 0xc33707d6,
101      3, 0xf4d50d87,
102      8, 0x455a14ed,
103     13, 0xa9e3e905,
104      2, 0xfcefa3f8,
105      7, 0x676f02d9,
106     12, 0x8d2a4c8a,
107      5, 0xfffa3942,
108      8, 0x8771f681,
109     11, 0x6d9d6122,
110     14, 0xfde5380c,
111      1, 0xa4beea44,
112      4, 0x4bdecfa9,
113      7, 0xf6bb4b60,
114     10, 0xbebfbc70,
115     13, 0x289b7ec6,
116      0, 0xeaa127fa,
117      3, 0xd4ef3085,
118      6,  0x4881d05,
119      9, 0xd9d4d039,
120     12, 0xe6db99e5,
121     15, 0x1fa27cf8,
122      2, 0xc4ac5665,
123      0, 0xf4292244,
124      7, 0x432aff97,
125     14, 0xab9423a7,
126      5, 0xfc93a039,
127     12, 0x655b59c3,
128      3, 0x8f0ccc92,
129     10, 0xffeff47d,
130      1, 0x85845dd1,
131      8, 0x6fa87e4f,
132     15, 0xfe2ce6e0,
133      6, 0xa3014314,
134     13, 0x4e0811a1,
135      4, 0xf7537e82,
136     11, 0xbd3af235,
137      2, 0x2ad7d2bb,
138      9, 0xeb86d391,
139 #endif
140     };
141 
142 #ifndef SDK_DIGEST_MD5_FAST
143     static u32 k[] =
144     {
145          1,  6, 11,  0,
146          5, 10, 15,  4,
147          9, 14,  3,  8,
148         13,  2,  7, 12,
149          5,  8, 11, 14,
150          1,  4,  7, 10,
151         13,  0,  3,  6,
152          9, 12, 15,  2,
153          0,  7, 14,  5,
154         12,  3, 10,  1,
155          8, 15,  6, 13,
156          4, 11,  2,  9,
157     };
158     u32 *kp;
159 #endif
160 
161     u32 a, b, c, d;
162     u32 *x;
163     u32 *xp, *tp;
164     int j;
165 
166     a = context->a;
167     b = context->b;
168     c = context->c;
169     d = context->d;
170 
171 #ifdef SDK_LITTLE_ENDIAN
172     x = context->buffer32;
173 #else
174 #error "Big Endian is not supported."
175 #endif
176 
177     xp = x;
178     tp = t;
179 
180     // /* Round 1. */
181     // /* Let [abcd k s i] denote the operation
182     //      a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
183     // /* Do the following 16 operations. */
184     // [ABCD  0  7  1]  [DABC  1 12  2]  [CDAB  2 17  3]  [BCDA  3 22  4]
185     // [ABCD  4  7  5]  [DABC  5 12  6]  [CDAB  6 17  7]  [BCDA  7 22  8]
186     // [ABCD  8  7  9]  [DABC  9 12  10]  [CDAB  10 17  11]  [BCDA  11 22  12]
187     // [ABCD  12  7  13]  [DABC  13 12  14]  [CDAB  14 17  15]  [BCDA  15 22  16]
188 
189     for (j = 0; j < 4; j++)
190     {
191         a = CalcRound1(a, b, c, d, *xp++,  7, *tp++);
192         d = CalcRound1(d, a, b, c, *xp++, 12, *tp++);
193         c = CalcRound1(c, d, a, b, *xp++, 17, *tp++);
194         b = CalcRound1(b, c, d, a, *xp++, 22, *tp++);
195     }
196 
197 #ifndef SDK_DIGEST_MD5_FAST
198     kp = k;
199 #endif
200 
201     // /* Round 2. */
202     // /* Let [abcd k s i] denote the operation
203     //      a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
204     // /* Do the following 16 operations. */
205     // [ABCD  1  5  17]  [DABC  6 9  18]  [CDAB  11 14  19]  [BCDA  0 20  20]
206     // [ABCD  5  5  21]  [DABC  10 9  22]  [CDAB  15 14  23]  [BCDA  4 20  24]
207     // [ABCD  9  5  25]  [DABC  14 9  26]  [CDAB  3 14  27]  [BCDA  8 20  28]
208     // [ABCD  13  5  29]  [DABC  2 9  30]  [CDAB  7 14  31]  [BCDA  12 20  32]
209 
210     for (j = 0; j < 4; j++)
211     {
212 #ifndef SDK_DIGEST_MD5_FAST
213         a = CalcRound2(a, b, c, d, x[*kp++],  5, *tp++);
214         d = CalcRound2(d, a, b, c, x[*kp++],  9, *tp++);
215         c = CalcRound2(c, d, a, b, x[*kp++], 14, *tp++);
216         b = CalcRound2(b, c, d, a, x[*kp++], 20, *tp++);
217 #else
218         a = CalcRound2(a, b, c, d, x[*(tp+0)],  5, *(tp+1));
219         d = CalcRound2(d, a, b, c, x[*(tp+2)],  9, *(tp+3));
220         c = CalcRound2(c, d, a, b, x[*(tp+4)], 14, *(tp+5));
221         b = CalcRound2(b, c, d, a, x[*(tp+6)], 20, *(tp+7));
222         tp += 8;
223 #endif
224     }
225 
226     // /* Round 3. */
227     // /* Let [abcd k s t] denote the operation
228     //      a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
229     // /* Do the following 16 operations. */
230     // [ABCD  5  4  33]  [DABC  8 11  34]  [CDAB  11 16  35]  [BCDA  14 23  36]
231     // [ABCD  1  4  37]  [DABC  4 11  38]  [CDAB  7 16  39]  [BCDA  10 23  40]
232     // [ABCD  13  4  41]  [DABC  0 11  42]  [CDAB  3 16  43]  [BCDA  6 23  44]
233     // [ABCD  9  4  45]  [DABC  12 11  46]  [CDAB  15 16  47]  [BCDA  2 23  48]
234 
235     for (j = 0; j < 4; j++)
236     {
237 #ifndef SDK_DIGEST_MD5_FAST
238         a = CalcRound3(a, b, c, d, x[*kp++],  4, *tp++);
239         d = CalcRound3(d, a, b, c, x[*kp++], 11, *tp++);
240         c = CalcRound3(c, d, a, b, x[*kp++], 16, *tp++);
241         b = CalcRound3(b, c, d, a, x[*kp++], 23, *tp++);
242 #else
243         a = CalcRound3(a, b, c, d, x[*(tp+0)],  4, *(tp+1));
244         d = CalcRound3(d, a, b, c, x[*(tp+2)], 11, *(tp+3));
245         c = CalcRound3(c, d, a, b, x[*(tp+4)], 16, *(tp+5));
246         b = CalcRound3(b, c, d, a, x[*(tp+6)], 23, *(tp+7));
247         tp += 8;
248 #endif
249     }
250 
251     // /* Round 4. */
252     // /* Let [abcd k s t] denote the operation
253     //      a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
254     // /* Do the following 16 operations. */
255     // [ABCD  0  6  49]  [DABC  7 10  50]  [CDAB  14 15  51]  [BCDA  5 21  52]
256     // [ABCD  12  6  53]  [DABC  3 10  54]  [CDAB  10 15  55]  [BCDA  1 21  56]
257     // [ABCD  8  6  57]  [DABC  15 10  58]  [CDAB  6 15  59]  [BCDA  13 21  60]
258     // [ABCD  4  6  61]  [DABC  11 10  62]  [CDAB  2 15  63]  [BCDA  9 21  64]
259 
260     for (j = 0; j < 4; j++)
261     {
262 #ifndef SDK_DIGEST_MD5_FAST
263         a = CalcRound4(a, b, c, d, x[*kp++],  6, *tp++);
264         d = CalcRound4(d, a, b, c, x[*kp++], 10, *tp++);
265         c = CalcRound4(c, d, a, b, x[*kp++], 15, *tp++);
266         b = CalcRound4(b, c, d, a, x[*kp++], 21, *tp++);
267 #else
268         a = CalcRound4(a, b, c, d, x[*(tp+0)],  6, *(tp+1));
269         d = CalcRound4(d, a, b, c, x[*(tp+2)], 10, *(tp+3));
270         c = CalcRound4(c, d, a, b, x[*(tp+4)], 15, *(tp+5));
271         b = CalcRound4(b, c, d, a, x[*(tp+6)], 21, *(tp+7));
272         tp += 8;
273 #endif
274     }
275 
276     context->a += a;
277     context->b += b;
278     context->c += c;
279     context->d += d;
280 }
281 
282 
283 
284 /*---------------------------------------------------------------------------*
285   Name:         MATH_MD5Init
286 
287   Description:  Initializes the MATHMD5Context structure used for requesting the MD5 value.
288 
289   Arguments:    context:   MATHMD5Context structure
290 
291   Returns:      None.
292  *---------------------------------------------------------------------------*/
293 void
MATH_MD5Init(MATHMD5Context * context)294 MATH_MD5Init(MATHMD5Context* context)
295 {
296     context->a = 0x67452301;
297     context->b = 0xefcdab89;
298     context->c = 0x98badcfe;
299     context->d = 0x10325476;
300     context->length = 0;
301 }
302 
303 /*---------------------------------------------------------------------------*
304   Name:         MATH_MD5Update
305 
306   Description:  Updates the MD5 value with given data.
307 
308   Arguments:    context:   MATHMD5Context structure
309                 input:   Pointer to input data.
310                 length:  Length of input data.
311 
312   Returns:      None.
313  *---------------------------------------------------------------------------*/
314 void
MATH_MD5Update(MATHMD5Context * context,const void * input,u32 length)315 MATH_MD5Update(MATHMD5Context* context, const void* input, u32 length)
316 {
317     u32 buffer_index, buffer_space;
318     s32 i;
319     u8* p;
320 
321     buffer_index = (u32)(context->length & 63); // (length % 64);
322     context->length += length;
323     buffer_space = 64 - buffer_index;
324 
325     if (buffer_space > length)
326     {
327         if (length > 0)
328         {
329             MI_CpuCopy8(input, &(context->buffer8[buffer_index]), length);
330         }
331         return;
332     }
333 
334     MI_CpuCopy8(input, &(context->buffer8[buffer_index]), buffer_space);
335     ProcessBlock(context);
336     p = ((u8*)input + buffer_space);
337     length -= buffer_space;
338 
339     i = (s32)(length >> 6); // length / 64
340     for (; i > 0; i--)
341     {
342         MI_CpuCopy8(p, context->buffer8, 64);
343         p += 64;
344         ProcessBlock(context);
345     }
346 
347     length &= 63; // length % 64
348     if (length > 0)
349     {
350         MI_CpuCopy8(p, context->buffer8, length);
351     }
352 }
353 
354 /*---------------------------------------------------------------------------*
355   Name:         MATH_MD5GetHash
356 
357   Description:  Gets the final MD5 value.
358 
359   Arguments:    context:   MATHMD5Context structure
360                 digest:   Pointer to the location where MD5 is stored.
361 
362   Returns:      None.
363  *---------------------------------------------------------------------------*/
364 void
MATH_MD5GetHash(MATHMD5Context * context,void * digest)365 MATH_MD5GetHash(MATHMD5Context * context, void *digest)
366 {
367     static u8 padding = 0x80;
368     u64 total_length;
369     u32 buffer_index, buffer_space;
370 
371     total_length = context->length << 3; // bytes to bits
372 
373     MATH_MD5Update(context, &padding, sizeof(u8));
374 
375     buffer_index = (u32)(context->length & 63); // (length % 64);
376     buffer_space = 64 - buffer_index;
377     if (buffer_space < sizeof(u64))
378     {
379         MI_CpuFill8(&(context->buffer8[buffer_index]), 0, buffer_space);
380         ProcessBlock(context);
381         buffer_index = 0;
382         buffer_space = 64;
383     }
384     if (buffer_space > sizeof(u64))
385     {
386         MI_CpuFill8(&(context->buffer8[buffer_index]), 0, buffer_space - sizeof(u64));
387     }
388     *(u64*)&(context->buffer8[64-sizeof(u64)]) = total_length;
389 
390     ProcessBlock(context);
391 
392     MI_CpuCopy8(context->state, digest, sizeof(context->state));
393 
394     MI_CpuFill8(context, 0, sizeof(*context));
395 }
396 
397 /*---------------------------------------------------------------------------*
398   Name:         MATH_CalcMD5
399 
400   Description:  Calculates MD5.
401 
402   Arguments:    digest:   Pointer to the location where MD5 is stored.
403                 data:    Pointer to input data.
404                 dataLength:   Length of input data.
405 
406   Returns:      None.
407  *---------------------------------------------------------------------------*/
MATH_CalcMD5(void * digest,const void * data,u32 dataLength)408 void MATH_CalcMD5(void *digest, const void *data, u32 dataLength)
409 {
410     MATHMD5Context context;
411     MATH_MD5Init(&context);
412     MATH_MD5Update(&context, data, dataLength);
413     MATH_MD5GetHash(&context, digest);
414 }
415 
416 
417 
418 // HMAC
419 
420 /*---------------------------------------------------------------------------*
421   Name:         MATH_CalcHMACMD5
422 
423   Description:  Calculates HMAC-MD5.
424 
425   Arguments:    digest:   Pointer to the location where HMAC-MD5 is stored.
426                 data:    Pointer to input data.
427                 dataLength:   Length of input data.
428                 key:    Pointer to the key
429                 keyLength:   Length of the key
430 
431   Returns:      None.
432  *---------------------------------------------------------------------------*/
MATH_CalcHMACMD5(void * digest,const void * bin_ptr,u32 bin_len,const void * key_ptr,u32 key_len)433 void MATH_CalcHMACMD5(void *digest, const void *bin_ptr, u32 bin_len, const void *key_ptr, u32 key_len)
434 {
435     MATHMD5Context context;
436     unsigned char   hash_buf[ MATH_MD5_BLOCK_SIZE ]; /* Hash value gotten from the hash function */
437 
438     MATHiHMACFuncs hash1funcs = {
439         MATH_MD5_DIGEST_SIZE,
440         (512/8),
441     };
442 
443     hash1funcs.context       = &context;
444     hash1funcs.hash_buf      = hash_buf;
445     hash1funcs.HashReset     = (void (*)(void*))                   MATH_MD5Init;
446     hash1funcs.HashSetSource = (void (*)(void*, const void*, u32)) MATH_MD5Update;
447     hash1funcs.HashGetDigest = (void (*)(void*, void*))            MATH_MD5GetHash;
448 
449     MATHi_CalcHMAC(digest, bin_ptr, bin_len, key_ptr, key_len, &hash1funcs);
450 }
451 
452 #ifdef SDK_TWLHYB
453 #ifdef SDK_ARM7
454 #include <twl/ltdwram_end.h>
455 #endif
456 #endif
457