CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
hrydgard

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/Crypto/md5.cpp
Views: 1401
1
/*
2
* RFC 1321 compliant MD5 implementation
3
*
4
* Copyright (C) 2006-2009, Paul Bakker <polarssl_maintainer at polarssl.org>
5
* All rights reserved.
6
*
7
* Joined copyright on original XySSL code with: Christophe Devine
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License along
20
* with this program; if not, write to the Free Software Foundation, Inc.,
21
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
*/
23
/*
24
* The MD5 algorithm was designed by Ron Rivest in 1991.
25
*
26
* http://www.ietf.org/rfc/rfc1321.txt
27
*/
28
29
//#include "polarssl/config.h"
30
31
#if defined(POLARSSL_MD5_C)
32
33
#include "polarssl/md5.h"
34
#else
35
#include "md5.h"
36
37
#include <string.h>
38
39
/*
40
* 32-bit integer manipulation macros (little endian)
41
*/
42
#ifndef GET_ULONG_LE
43
#define GET_ULONG_LE(n,b,i) \
44
{ \
45
(n) = ( (unsigned long) (b)[(i) ] ) \
46
| ( (unsigned long) (b)[(i) + 1] << 8 ) \
47
| ( (unsigned long) (b)[(i) + 2] << 16 ) \
48
| ( (unsigned long) (b)[(i) + 3] << 24 ); \
49
}
50
#endif
51
52
#ifndef PUT_ULONG_LE
53
#define PUT_ULONG_LE(n,b,i) \
54
{ \
55
(b)[(i) ] = (unsigned char) ( (n) ); \
56
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
57
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
58
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
59
}
60
#endif
61
62
/*
63
* MD5 context setup
64
*/
65
void ppsspp_md5_starts( md5_context *ctx )
66
{
67
ctx->total[0] = 0;
68
ctx->total[1] = 0;
69
70
ctx->state[0] = 0x67452301;
71
ctx->state[1] = 0xEFCDAB89;
72
ctx->state[2] = 0x98BADCFE;
73
ctx->state[3] = 0x10325476;
74
}
75
76
static void ppsspp_md5_process( md5_context *ctx, const unsigned char data[64] )
77
{
78
unsigned long X[16], A, B, C, D;
79
80
GET_ULONG_LE( X[ 0], data, 0 );
81
GET_ULONG_LE( X[ 1], data, 4 );
82
GET_ULONG_LE( X[ 2], data, 8 );
83
GET_ULONG_LE( X[ 3], data, 12 );
84
GET_ULONG_LE( X[ 4], data, 16 );
85
GET_ULONG_LE( X[ 5], data, 20 );
86
GET_ULONG_LE( X[ 6], data, 24 );
87
GET_ULONG_LE( X[ 7], data, 28 );
88
GET_ULONG_LE( X[ 8], data, 32 );
89
GET_ULONG_LE( X[ 9], data, 36 );
90
GET_ULONG_LE( X[10], data, 40 );
91
GET_ULONG_LE( X[11], data, 44 );
92
GET_ULONG_LE( X[12], data, 48 );
93
GET_ULONG_LE( X[13], data, 52 );
94
GET_ULONG_LE( X[14], data, 56 );
95
GET_ULONG_LE( X[15], data, 60 );
96
97
#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
98
99
#define P(a,b,c,d,k,s,t) \
100
{ \
101
a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \
102
}
103
104
A = ctx->state[0];
105
B = ctx->state[1];
106
C = ctx->state[2];
107
D = ctx->state[3];
108
109
#define F(x,y,z) (z ^ (x & (y ^ z)))
110
111
P( A, B, C, D, 0, 7, 0xD76AA478 );
112
P( D, A, B, C, 1, 12, 0xE8C7B756 );
113
P( C, D, A, B, 2, 17, 0x242070DB );
114
P( B, C, D, A, 3, 22, 0xC1BDCEEE );
115
P( A, B, C, D, 4, 7, 0xF57C0FAF );
116
P( D, A, B, C, 5, 12, 0x4787C62A );
117
P( C, D, A, B, 6, 17, 0xA8304613 );
118
P( B, C, D, A, 7, 22, 0xFD469501 );
119
P( A, B, C, D, 8, 7, 0x698098D8 );
120
P( D, A, B, C, 9, 12, 0x8B44F7AF );
121
P( C, D, A, B, 10, 17, 0xFFFF5BB1 );
122
P( B, C, D, A, 11, 22, 0x895CD7BE );
123
P( A, B, C, D, 12, 7, 0x6B901122 );
124
P( D, A, B, C, 13, 12, 0xFD987193 );
125
P( C, D, A, B, 14, 17, 0xA679438E );
126
P( B, C, D, A, 15, 22, 0x49B40821 );
127
128
#undef F
129
130
#define F(x,y,z) (y ^ (z & (x ^ y)))
131
132
P( A, B, C, D, 1, 5, 0xF61E2562 );
133
P( D, A, B, C, 6, 9, 0xC040B340 );
134
P( C, D, A, B, 11, 14, 0x265E5A51 );
135
P( B, C, D, A, 0, 20, 0xE9B6C7AA );
136
P( A, B, C, D, 5, 5, 0xD62F105D );
137
P( D, A, B, C, 10, 9, 0x02441453 );
138
P( C, D, A, B, 15, 14, 0xD8A1E681 );
139
P( B, C, D, A, 4, 20, 0xE7D3FBC8 );
140
P( A, B, C, D, 9, 5, 0x21E1CDE6 );
141
P( D, A, B, C, 14, 9, 0xC33707D6 );
142
P( C, D, A, B, 3, 14, 0xF4D50D87 );
143
P( B, C, D, A, 8, 20, 0x455A14ED );
144
P( A, B, C, D, 13, 5, 0xA9E3E905 );
145
P( D, A, B, C, 2, 9, 0xFCEFA3F8 );
146
P( C, D, A, B, 7, 14, 0x676F02D9 );
147
P( B, C, D, A, 12, 20, 0x8D2A4C8A );
148
149
#undef F
150
151
#define F(x,y,z) (x ^ y ^ z)
152
153
P( A, B, C, D, 5, 4, 0xFFFA3942 );
154
P( D, A, B, C, 8, 11, 0x8771F681 );
155
P( C, D, A, B, 11, 16, 0x6D9D6122 );
156
P( B, C, D, A, 14, 23, 0xFDE5380C );
157
P( A, B, C, D, 1, 4, 0xA4BEEA44 );
158
P( D, A, B, C, 4, 11, 0x4BDECFA9 );
159
P( C, D, A, B, 7, 16, 0xF6BB4B60 );
160
P( B, C, D, A, 10, 23, 0xBEBFBC70 );
161
P( A, B, C, D, 13, 4, 0x289B7EC6 );
162
P( D, A, B, C, 0, 11, 0xEAA127FA );
163
P( C, D, A, B, 3, 16, 0xD4EF3085 );
164
P( B, C, D, A, 6, 23, 0x04881D05 );
165
P( A, B, C, D, 9, 4, 0xD9D4D039 );
166
P( D, A, B, C, 12, 11, 0xE6DB99E5 );
167
P( C, D, A, B, 15, 16, 0x1FA27CF8 );
168
P( B, C, D, A, 2, 23, 0xC4AC5665 );
169
170
#undef F
171
172
#define F(x,y,z) (y ^ (x | ~z))
173
174
P( A, B, C, D, 0, 6, 0xF4292244 );
175
P( D, A, B, C, 7, 10, 0x432AFF97 );
176
P( C, D, A, B, 14, 15, 0xAB9423A7 );
177
P( B, C, D, A, 5, 21, 0xFC93A039 );
178
P( A, B, C, D, 12, 6, 0x655B59C3 );
179
P( D, A, B, C, 3, 10, 0x8F0CCC92 );
180
P( C, D, A, B, 10, 15, 0xFFEFF47D );
181
P( B, C, D, A, 1, 21, 0x85845DD1 );
182
P( A, B, C, D, 8, 6, 0x6FA87E4F );
183
P( D, A, B, C, 15, 10, 0xFE2CE6E0 );
184
P( C, D, A, B, 6, 15, 0xA3014314 );
185
P( B, C, D, A, 13, 21, 0x4E0811A1 );
186
P( A, B, C, D, 4, 6, 0xF7537E82 );
187
P( D, A, B, C, 11, 10, 0xBD3AF235 );
188
P( C, D, A, B, 2, 15, 0x2AD7D2BB );
189
P( B, C, D, A, 9, 21, 0xEB86D391 );
190
191
#undef F
192
193
ctx->state[0] += A;
194
ctx->state[1] += B;
195
ctx->state[2] += C;
196
ctx->state[3] += D;
197
}
198
199
/*
200
* MD5 process buffer
201
*/
202
void ppsspp_md5_update( md5_context *ctx, unsigned char *input, int ilen )
203
{
204
int fill;
205
unsigned long left;
206
207
if( ilen <= 0 )
208
return;
209
210
left = ctx->total[0] & 0x3F;
211
fill = 64 - left;
212
213
ctx->total[0] += ilen;
214
ctx->total[0] &= 0xFFFFFFFF;
215
216
if( ctx->total[0] < (unsigned long) ilen )
217
ctx->total[1]++;
218
219
if( left && ilen >= fill )
220
{
221
memcpy( (void *) (ctx->buffer + left),
222
(void *) input, fill );
223
ppsspp_md5_process( ctx, ctx->buffer );
224
input += fill;
225
ilen -= fill;
226
left = 0;
227
}
228
229
while( ilen >= 64 )
230
{
231
ppsspp_md5_process( ctx, input );
232
input += 64;
233
ilen -= 64;
234
}
235
236
if( ilen > 0 )
237
{
238
memcpy( (void *) (ctx->buffer + left),
239
(void *) input, ilen );
240
}
241
}
242
243
static const unsigned char md5_padding[64] =
244
{
245
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
246
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
247
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
248
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
249
};
250
251
/*
252
* MD5 final digest
253
*/
254
void ppsspp_md5_finish( md5_context *ctx, unsigned char output[16] )
255
{
256
unsigned long last, padn;
257
unsigned long high, low;
258
unsigned char msglen[8];
259
260
high = ( ctx->total[0] >> 29 )
261
| ( ctx->total[1] << 3 );
262
low = ( ctx->total[0] << 3 );
263
264
PUT_ULONG_LE( low, msglen, 0 );
265
PUT_ULONG_LE( high, msglen, 4 );
266
267
last = ctx->total[0] & 0x3F;
268
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
269
270
ppsspp_md5_update( ctx, (unsigned char *) md5_padding, padn );
271
ppsspp_md5_update( ctx, msglen, 8 );
272
273
PUT_ULONG_LE( ctx->state[0], output, 0 );
274
PUT_ULONG_LE( ctx->state[1], output, 4 );
275
PUT_ULONG_LE( ctx->state[2], output, 8 );
276
PUT_ULONG_LE( ctx->state[3], output, 12 );
277
}
278
279
/*
280
* output = MD5( input buffer )
281
*/
282
void ppsspp_md5( unsigned char *input, int ilen, unsigned char output[16] )
283
{
284
md5_context ctx;
285
286
ppsspp_md5_starts( &ctx );
287
ppsspp_md5_update( &ctx, input, ilen );
288
ppsspp_md5_finish( &ctx, output );
289
290
memset( &ctx, 0, sizeof( md5_context ) );
291
}
292
293
/*
294
* MD5 HMAC context setup
295
*/
296
void ppsspp_md5_hmac_starts( md5_context *ctx, unsigned char *key, int keylen )
297
{
298
int i;
299
unsigned char sum[16];
300
301
if( keylen > 64 )
302
{
303
ppsspp_md5( key, keylen, sum );
304
keylen = 16;
305
key = sum;
306
}
307
308
memset( ctx->ipad, 0x36, 64 );
309
memset( ctx->opad, 0x5C, 64 );
310
311
for( i = 0; i < keylen; i++ )
312
{
313
ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] );
314
ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] );
315
}
316
317
ppsspp_md5_starts( ctx );
318
ppsspp_md5_update( ctx, ctx->ipad, 64 );
319
320
memset( sum, 0, sizeof( sum ) );
321
}
322
323
/*
324
* MD5 HMAC process buffer
325
*/
326
void ppsspp_md5_hmac_update( md5_context *ctx, unsigned char *input, int ilen )
327
{
328
ppsspp_md5_update( ctx, input, ilen );
329
}
330
331
/*
332
* MD5 HMAC final digest
333
*/
334
void ppsspp_md5_hmac_finish( md5_context *ctx, unsigned char output[16] )
335
{
336
unsigned char tmpbuf[16];
337
338
ppsspp_md5_finish( ctx, tmpbuf );
339
ppsspp_md5_starts( ctx );
340
ppsspp_md5_update( ctx, ctx->opad, 64 );
341
ppsspp_md5_update( ctx, tmpbuf, 16 );
342
ppsspp_md5_finish( ctx, output );
343
344
memset( tmpbuf, 0, sizeof( tmpbuf ) );
345
}
346
347
/*
348
* output = HMAC-MD5( hmac key, input buffer )
349
*/
350
void ppsspp_md5_hmac( unsigned char *key, int keylen, unsigned char *input, int ilen,
351
unsigned char output[16] )
352
{
353
md5_context ctx;
354
355
ppsspp_md5_hmac_starts( &ctx, key, keylen );
356
ppsspp_md5_hmac_update( &ctx, input, ilen );
357
ppsspp_md5_hmac_finish( &ctx, output );
358
359
memset( &ctx, 0, sizeof( md5_context ) );
360
}
361
362
#if defined(POLARSSL_SELF_TEST)
363
/*
364
* RFC 1321 test vectors
365
*/
366
static unsigned char md5_test_buf[7][81] =
367
{
368
{ "" },
369
{ "a" },
370
{ "abc" },
371
{ "message digest" },
372
{ "abcdefghijklmnopqrstuvwxyz" },
373
{ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
374
{ "12345678901234567890123456789012345678901234567890123456789012" \
375
"345678901234567890" }
376
};
377
378
static const int md5_test_buflen[7] =
379
{
380
0, 1, 3, 14, 26, 62, 80
381
};
382
383
static const unsigned char md5_test_sum[7][16] =
384
{
385
{ 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
386
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E },
387
{ 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8,
388
0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 },
389
{ 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0,
390
0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 },
391
{ 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D,
392
0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 },
393
{ 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00,
394
0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B },
395
{ 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5,
396
0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F },
397
{ 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55,
398
0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A }
399
};
400
401
/*
402
* RFC 2202 test vectors
403
*/
404
static unsigned char md5_hmac_test_key[7][26] =
405
{
406
{ "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" },
407
{ "Jefe" },
408
{ "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" },
409
{ "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
410
"\x11\x12\x13\x14\x15\x16\x17\x18\x19" },
411
{ "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" },
412
{ "" }, /* 0xAA 80 times */
413
{ "" }
414
};
415
416
static const int md5_hmac_test_keylen[7] =
417
{
418
16, 4, 16, 25, 16, 80, 80
419
};
420
421
static unsigned char md5_hmac_test_buf[7][74] =
422
{
423
{ "Hi There" },
424
{ "what do ya want for nothing?" },
425
{ "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
426
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
427
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
428
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
429
"\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" },
430
{ "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
431
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
432
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
433
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
434
"\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" },
435
{ "Test With Truncation" },
436
{ "Test Using Larger Than Block-Size Key - Hash Key First" },
437
{ "Test Using Larger Than Block-Size Key and Larger"
438
" Than One Block-Size Data" }
439
};
440
441
static const int md5_hmac_test_buflen[7] =
442
{
443
8, 28, 50, 50, 20, 54, 73
444
};
445
446
static const unsigned char md5_hmac_test_sum[7][16] =
447
{
448
{ 0x92, 0x94, 0x72, 0x7A, 0x36, 0x38, 0xBB, 0x1C,
449
0x13, 0xF4, 0x8E, 0xF8, 0x15, 0x8B, 0xFC, 0x9D },
450
{ 0x75, 0x0C, 0x78, 0x3E, 0x6A, 0xB0, 0xB5, 0x03,
451
0xEA, 0xA8, 0x6E, 0x31, 0x0A, 0x5D, 0xB7, 0x38 },
452
{ 0x56, 0xBE, 0x34, 0x52, 0x1D, 0x14, 0x4C, 0x88,
453
0xDB, 0xB8, 0xC7, 0x33, 0xF0, 0xE8, 0xB3, 0xF6 },
454
{ 0x69, 0x7E, 0xAF, 0x0A, 0xCA, 0x3A, 0x3A, 0xEA,
455
0x3A, 0x75, 0x16, 0x47, 0x46, 0xFF, 0xAA, 0x79 },
456
{ 0x56, 0x46, 0x1E, 0xF2, 0x34, 0x2E, 0xDC, 0x00,
457
0xF9, 0xBA, 0xB9, 0x95 },
458
{ 0x6B, 0x1A, 0xB7, 0xFE, 0x4B, 0xD7, 0xBF, 0x8F,
459
0x0B, 0x62, 0xE6, 0xCE, 0x61, 0xB9, 0xD0, 0xCD },
460
{ 0x6F, 0x63, 0x0F, 0xAD, 0x67, 0xCD, 0xA0, 0xEE,
461
0x1F, 0xB1, 0xF5, 0x62, 0xDB, 0x3A, 0xA5, 0x3E }
462
};
463
464
/*
465
* Checkup routine
466
*/
467
int ppsspp_md5_self_test( int verbose )
468
{
469
int i, buflen;
470
unsigned char buf[1024];
471
unsigned char md5sum[16];
472
md5_context ctx;
473
474
for( i = 0; i < 7; i++ )
475
{
476
if( verbose != 0 )
477
printf( " MD5 test #%d: ", i + 1 );
478
479
md5( md5_test_buf[i], md5_test_buflen[i], md5sum );
480
481
if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 )
482
{
483
if( verbose != 0 )
484
printf( "failed\n" );
485
486
return( 1 );
487
}
488
489
if( verbose != 0 )
490
printf( "passed\n" );
491
}
492
493
if( verbose != 0 )
494
printf( "\n" );
495
496
for( i = 0; i < 7; i++ )
497
{
498
if( verbose != 0 )
499
printf( " HMAC-MD5 test #%d: ", i + 1 );
500
501
if( i == 5 || i == 6 )
502
{
503
memset( buf, '\xAA', buflen = 80 );
504
md5_hmac_starts( &ctx, buf, buflen );
505
}
506
else
507
md5_hmac_starts( &ctx, md5_hmac_test_key[i],
508
md5_hmac_test_keylen[i] );
509
510
md5_hmac_update( &ctx, md5_hmac_test_buf[i],
511
md5_hmac_test_buflen[i] );
512
513
md5_hmac_finish( &ctx, md5sum );
514
515
buflen = ( i == 4 ) ? 12 : 16;
516
517
if( memcmp( md5sum, md5_hmac_test_sum[i], buflen ) != 0 )
518
{
519
if( verbose != 0 )
520
printf( "failed\n" );
521
522
return( 1 );
523
}
524
525
if( verbose != 0 )
526
printf( "passed\n" );
527
}
528
529
if( verbose != 0 )
530
printf( "\n" );
531
532
return( 0 );
533
}
534
535
#endif
536
537
#endif
538
539