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