| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* md5.c - an implementation of the MD5 algorithm, based on RFC 1321. |
|
2
|
|
|
|
|
|
|
* |
|
3
|
|
|
|
|
|
|
* Copyright: 2007-2012 Aleksey Kravchenko |
|
4
|
|
|
|
|
|
|
* |
|
5
|
|
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a |
|
6
|
|
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"), |
|
7
|
|
|
|
|
|
|
* to deal in the Software without restriction, including without limitation |
|
8
|
|
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
9
|
|
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the |
|
10
|
|
|
|
|
|
|
* Software is furnished to do so. |
|
11
|
|
|
|
|
|
|
* |
|
12
|
|
|
|
|
|
|
* This program is distributed in the hope that it will be useful, but |
|
13
|
|
|
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
|
14
|
|
|
|
|
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk! |
|
15
|
|
|
|
|
|
|
*/ |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
#include |
|
18
|
|
|
|
|
|
|
#include "byte_order.h" |
|
19
|
|
|
|
|
|
|
#include "md5.h" |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
/** |
|
22
|
|
|
|
|
|
|
* Initialize context before calculaing hash. |
|
23
|
|
|
|
|
|
|
* |
|
24
|
|
|
|
|
|
|
* @param ctx context to initialize |
|
25
|
|
|
|
|
|
|
*/ |
|
26
|
8
|
|
|
|
|
|
void rhash_md5_init(md5_ctx *ctx) |
|
27
|
|
|
|
|
|
|
{ |
|
28
|
8
|
|
|
|
|
|
ctx->length = 0; |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
/* initialize state */ |
|
31
|
8
|
|
|
|
|
|
ctx->hash[0] = 0x67452301; |
|
32
|
8
|
|
|
|
|
|
ctx->hash[1] = 0xefcdab89; |
|
33
|
8
|
|
|
|
|
|
ctx->hash[2] = 0x98badcfe; |
|
34
|
8
|
|
|
|
|
|
ctx->hash[3] = 0x10325476; |
|
35
|
8
|
|
|
|
|
|
} |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
/* First, define four auxiliary functions that each take as input |
|
38
|
|
|
|
|
|
|
* three 32-bit words and returns a 32-bit word.*/ |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
/* F(x,y,z) = ((y XOR z) AND x) XOR z - is faster then original version */ |
|
41
|
|
|
|
|
|
|
#define MD5_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z)) |
|
42
|
|
|
|
|
|
|
#define MD5_G(x, y, z) (((x) & (z)) | ((y) & (~z))) |
|
43
|
|
|
|
|
|
|
#define MD5_H(x, y, z) ((x) ^ (y) ^ (z)) |
|
44
|
|
|
|
|
|
|
#define MD5_I(x, y, z) ((y) ^ ((x) | (~z))) |
|
45
|
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
/* transformations for rounds 1, 2, 3, and 4. */ |
|
47
|
|
|
|
|
|
|
#define MD5_ROUND1(a, b, c, d, x, s, ac) { \ |
|
48
|
|
|
|
|
|
|
(a) += MD5_F((b), (c), (d)) + (x) + (ac); \ |
|
49
|
|
|
|
|
|
|
(a) = ROTL32((a), (s)); \ |
|
50
|
|
|
|
|
|
|
(a) += (b); \ |
|
51
|
|
|
|
|
|
|
} |
|
52
|
|
|
|
|
|
|
#define MD5_ROUND2(a, b, c, d, x, s, ac) { \ |
|
53
|
|
|
|
|
|
|
(a) += MD5_G((b), (c), (d)) + (x) + (ac); \ |
|
54
|
|
|
|
|
|
|
(a) = ROTL32((a), (s)); \ |
|
55
|
|
|
|
|
|
|
(a) += (b); \ |
|
56
|
|
|
|
|
|
|
} |
|
57
|
|
|
|
|
|
|
#define MD5_ROUND3(a, b, c, d, x, s, ac) { \ |
|
58
|
|
|
|
|
|
|
(a) += MD5_H((b), (c), (d)) + (x) + (ac); \ |
|
59
|
|
|
|
|
|
|
(a) = ROTL32((a), (s)); \ |
|
60
|
|
|
|
|
|
|
(a) += (b); \ |
|
61
|
|
|
|
|
|
|
} |
|
62
|
|
|
|
|
|
|
#define MD5_ROUND4(a, b, c, d, x, s, ac) { \ |
|
63
|
|
|
|
|
|
|
(a) += MD5_I((b), (c), (d)) + (x) + (ac); \ |
|
64
|
|
|
|
|
|
|
(a) = ROTL32((a), (s)); \ |
|
65
|
|
|
|
|
|
|
(a) += (b); \ |
|
66
|
|
|
|
|
|
|
} |
|
67
|
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
/** |
|
69
|
|
|
|
|
|
|
* The core transformation. Process a 512-bit block. |
|
70
|
|
|
|
|
|
|
* The function has been taken from RFC 1321 with little changes. |
|
71
|
|
|
|
|
|
|
* |
|
72
|
|
|
|
|
|
|
* @param state algorithm state |
|
73
|
|
|
|
|
|
|
* @param x the message block to process |
|
74
|
|
|
|
|
|
|
*/ |
|
75
|
8
|
|
|
|
|
|
static void rhash_md5_process_block(unsigned state[4], const unsigned* x) |
|
76
|
|
|
|
|
|
|
{ |
|
77
|
|
|
|
|
|
|
register unsigned a, b, c, d; |
|
78
|
8
|
|
|
|
|
|
a = state[0]; |
|
79
|
8
|
|
|
|
|
|
b = state[1]; |
|
80
|
8
|
|
|
|
|
|
c = state[2]; |
|
81
|
8
|
|
|
|
|
|
d = state[3]; |
|
82
|
|
|
|
|
|
|
|
|
83
|
8
|
|
|
|
|
|
MD5_ROUND1(a, b, c, d, x[ 0], 7, 0xd76aa478); |
|
84
|
8
|
|
|
|
|
|
MD5_ROUND1(d, a, b, c, x[ 1], 12, 0xe8c7b756); |
|
85
|
8
|
|
|
|
|
|
MD5_ROUND1(c, d, a, b, x[ 2], 17, 0x242070db); |
|
86
|
8
|
|
|
|
|
|
MD5_ROUND1(b, c, d, a, x[ 3], 22, 0xc1bdceee); |
|
87
|
8
|
|
|
|
|
|
MD5_ROUND1(a, b, c, d, x[ 4], 7, 0xf57c0faf); |
|
88
|
8
|
|
|
|
|
|
MD5_ROUND1(d, a, b, c, x[ 5], 12, 0x4787c62a); |
|
89
|
8
|
|
|
|
|
|
MD5_ROUND1(c, d, a, b, x[ 6], 17, 0xa8304613); |
|
90
|
8
|
|
|
|
|
|
MD5_ROUND1(b, c, d, a, x[ 7], 22, 0xfd469501); |
|
91
|
8
|
|
|
|
|
|
MD5_ROUND1(a, b, c, d, x[ 8], 7, 0x698098d8); |
|
92
|
8
|
|
|
|
|
|
MD5_ROUND1(d, a, b, c, x[ 9], 12, 0x8b44f7af); |
|
93
|
8
|
|
|
|
|
|
MD5_ROUND1(c, d, a, b, x[10], 17, 0xffff5bb1); |
|
94
|
8
|
|
|
|
|
|
MD5_ROUND1(b, c, d, a, x[11], 22, 0x895cd7be); |
|
95
|
8
|
|
|
|
|
|
MD5_ROUND1(a, b, c, d, x[12], 7, 0x6b901122); |
|
96
|
8
|
|
|
|
|
|
MD5_ROUND1(d, a, b, c, x[13], 12, 0xfd987193); |
|
97
|
8
|
|
|
|
|
|
MD5_ROUND1(c, d, a, b, x[14], 17, 0xa679438e); |
|
98
|
8
|
|
|
|
|
|
MD5_ROUND1(b, c, d, a, x[15], 22, 0x49b40821); |
|
99
|
|
|
|
|
|
|
|
|
100
|
8
|
|
|
|
|
|
MD5_ROUND2(a, b, c, d, x[ 1], 5, 0xf61e2562); |
|
101
|
8
|
|
|
|
|
|
MD5_ROUND2(d, a, b, c, x[ 6], 9, 0xc040b340); |
|
102
|
8
|
|
|
|
|
|
MD5_ROUND2(c, d, a, b, x[11], 14, 0x265e5a51); |
|
103
|
8
|
|
|
|
|
|
MD5_ROUND2(b, c, d, a, x[ 0], 20, 0xe9b6c7aa); |
|
104
|
8
|
|
|
|
|
|
MD5_ROUND2(a, b, c, d, x[ 5], 5, 0xd62f105d); |
|
105
|
8
|
|
|
|
|
|
MD5_ROUND2(d, a, b, c, x[10], 9, 0x2441453); |
|
106
|
8
|
|
|
|
|
|
MD5_ROUND2(c, d, a, b, x[15], 14, 0xd8a1e681); |
|
107
|
8
|
|
|
|
|
|
MD5_ROUND2(b, c, d, a, x[ 4], 20, 0xe7d3fbc8); |
|
108
|
8
|
|
|
|
|
|
MD5_ROUND2(a, b, c, d, x[ 9], 5, 0x21e1cde6); |
|
109
|
8
|
|
|
|
|
|
MD5_ROUND2(d, a, b, c, x[14], 9, 0xc33707d6); |
|
110
|
8
|
|
|
|
|
|
MD5_ROUND2(c, d, a, b, x[ 3], 14, 0xf4d50d87); |
|
111
|
8
|
|
|
|
|
|
MD5_ROUND2(b, c, d, a, x[ 8], 20, 0x455a14ed); |
|
112
|
8
|
|
|
|
|
|
MD5_ROUND2(a, b, c, d, x[13], 5, 0xa9e3e905); |
|
113
|
8
|
|
|
|
|
|
MD5_ROUND2(d, a, b, c, x[ 2], 9, 0xfcefa3f8); |
|
114
|
8
|
|
|
|
|
|
MD5_ROUND2(c, d, a, b, x[ 7], 14, 0x676f02d9); |
|
115
|
8
|
|
|
|
|
|
MD5_ROUND2(b, c, d, a, x[12], 20, 0x8d2a4c8a); |
|
116
|
|
|
|
|
|
|
|
|
117
|
8
|
|
|
|
|
|
MD5_ROUND3(a, b, c, d, x[ 5], 4, 0xfffa3942); |
|
118
|
8
|
|
|
|
|
|
MD5_ROUND3(d, a, b, c, x[ 8], 11, 0x8771f681); |
|
119
|
8
|
|
|
|
|
|
MD5_ROUND3(c, d, a, b, x[11], 16, 0x6d9d6122); |
|
120
|
8
|
|
|
|
|
|
MD5_ROUND3(b, c, d, a, x[14], 23, 0xfde5380c); |
|
121
|
8
|
|
|
|
|
|
MD5_ROUND3(a, b, c, d, x[ 1], 4, 0xa4beea44); |
|
122
|
8
|
|
|
|
|
|
MD5_ROUND3(d, a, b, c, x[ 4], 11, 0x4bdecfa9); |
|
123
|
8
|
|
|
|
|
|
MD5_ROUND3(c, d, a, b, x[ 7], 16, 0xf6bb4b60); |
|
124
|
8
|
|
|
|
|
|
MD5_ROUND3(b, c, d, a, x[10], 23, 0xbebfbc70); |
|
125
|
8
|
|
|
|
|
|
MD5_ROUND3(a, b, c, d, x[13], 4, 0x289b7ec6); |
|
126
|
8
|
|
|
|
|
|
MD5_ROUND3(d, a, b, c, x[ 0], 11, 0xeaa127fa); |
|
127
|
8
|
|
|
|
|
|
MD5_ROUND3(c, d, a, b, x[ 3], 16, 0xd4ef3085); |
|
128
|
8
|
|
|
|
|
|
MD5_ROUND3(b, c, d, a, x[ 6], 23, 0x4881d05); |
|
129
|
8
|
|
|
|
|
|
MD5_ROUND3(a, b, c, d, x[ 9], 4, 0xd9d4d039); |
|
130
|
8
|
|
|
|
|
|
MD5_ROUND3(d, a, b, c, x[12], 11, 0xe6db99e5); |
|
131
|
8
|
|
|
|
|
|
MD5_ROUND3(c, d, a, b, x[15], 16, 0x1fa27cf8); |
|
132
|
8
|
|
|
|
|
|
MD5_ROUND3(b, c, d, a, x[ 2], 23, 0xc4ac5665); |
|
133
|
|
|
|
|
|
|
|
|
134
|
8
|
|
|
|
|
|
MD5_ROUND4(a, b, c, d, x[ 0], 6, 0xf4292244); |
|
135
|
8
|
|
|
|
|
|
MD5_ROUND4(d, a, b, c, x[ 7], 10, 0x432aff97); |
|
136
|
8
|
|
|
|
|
|
MD5_ROUND4(c, d, a, b, x[14], 15, 0xab9423a7); |
|
137
|
8
|
|
|
|
|
|
MD5_ROUND4(b, c, d, a, x[ 5], 21, 0xfc93a039); |
|
138
|
8
|
|
|
|
|
|
MD5_ROUND4(a, b, c, d, x[12], 6, 0x655b59c3); |
|
139
|
8
|
|
|
|
|
|
MD5_ROUND4(d, a, b, c, x[ 3], 10, 0x8f0ccc92); |
|
140
|
8
|
|
|
|
|
|
MD5_ROUND4(c, d, a, b, x[10], 15, 0xffeff47d); |
|
141
|
8
|
|
|
|
|
|
MD5_ROUND4(b, c, d, a, x[ 1], 21, 0x85845dd1); |
|
142
|
8
|
|
|
|
|
|
MD5_ROUND4(a, b, c, d, x[ 8], 6, 0x6fa87e4f); |
|
143
|
8
|
|
|
|
|
|
MD5_ROUND4(d, a, b, c, x[15], 10, 0xfe2ce6e0); |
|
144
|
8
|
|
|
|
|
|
MD5_ROUND4(c, d, a, b, x[ 6], 15, 0xa3014314); |
|
145
|
8
|
|
|
|
|
|
MD5_ROUND4(b, c, d, a, x[13], 21, 0x4e0811a1); |
|
146
|
8
|
|
|
|
|
|
MD5_ROUND4(a, b, c, d, x[ 4], 6, 0xf7537e82); |
|
147
|
8
|
|
|
|
|
|
MD5_ROUND4(d, a, b, c, x[11], 10, 0xbd3af235); |
|
148
|
8
|
|
|
|
|
|
MD5_ROUND4(c, d, a, b, x[ 2], 15, 0x2ad7d2bb); |
|
149
|
8
|
|
|
|
|
|
MD5_ROUND4(b, c, d, a, x[ 9], 21, 0xeb86d391); |
|
150
|
|
|
|
|
|
|
|
|
151
|
8
|
|
|
|
|
|
state[0] += a; |
|
152
|
8
|
|
|
|
|
|
state[1] += b; |
|
153
|
8
|
|
|
|
|
|
state[2] += c; |
|
154
|
8
|
|
|
|
|
|
state[3] += d; |
|
155
|
8
|
|
|
|
|
|
} |
|
156
|
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
/** |
|
158
|
|
|
|
|
|
|
* Calculate message hash. |
|
159
|
|
|
|
|
|
|
* Can be called repeatedly with chunks of the message to be hashed. |
|
160
|
|
|
|
|
|
|
* |
|
161
|
|
|
|
|
|
|
* @param ctx the algorithm context containing current hashing state |
|
162
|
|
|
|
|
|
|
* @param msg message chunk |
|
163
|
|
|
|
|
|
|
* @param size length of the message chunk |
|
164
|
|
|
|
|
|
|
*/ |
|
165
|
7
|
|
|
|
|
|
void rhash_md5_update(md5_ctx *ctx, const unsigned char* msg, size_t size) |
|
166
|
|
|
|
|
|
|
{ |
|
167
|
7
|
|
|
|
|
|
unsigned index = (unsigned)ctx->length & 63; |
|
168
|
7
|
|
|
|
|
|
ctx->length += size; |
|
169
|
|
|
|
|
|
|
|
|
170
|
|
|
|
|
|
|
/* fill partial block */ |
|
171
|
7
|
50
|
|
|
|
|
if (index) { |
|
172
|
0
|
|
|
|
|
|
unsigned left = md5_block_size - index; |
|
173
|
0
|
|
|
|
|
|
le32_copy((char*)ctx->message, index, msg, (size < left ? size : left)); |
|
174
|
0
|
0
|
|
|
|
|
if (size < left) return; |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
/* process partial block */ |
|
177
|
0
|
|
|
|
|
|
rhash_md5_process_block(ctx->hash, ctx->message); |
|
178
|
0
|
|
|
|
|
|
msg += left; |
|
179
|
0
|
|
|
|
|
|
size -= left; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
7
|
50
|
|
|
|
|
while (size >= md5_block_size) { |
|
182
|
|
|
|
|
|
|
unsigned* aligned_message_block; |
|
183
|
0
|
0
|
|
|
|
|
if (IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) { |
|
184
|
|
|
|
|
|
|
/* the most common case is processing a 32-bit aligned message |
|
185
|
|
|
|
|
|
|
on a little-endian CPU without copying it */ |
|
186
|
0
|
|
|
|
|
|
aligned_message_block = (unsigned*)msg; |
|
187
|
|
|
|
|
|
|
} else { |
|
188
|
0
|
|
|
|
|
|
le32_copy(ctx->message, 0, msg, md5_block_size); |
|
189
|
0
|
|
|
|
|
|
aligned_message_block = ctx->message; |
|
190
|
|
|
|
|
|
|
} |
|
191
|
|
|
|
|
|
|
|
|
192
|
0
|
|
|
|
|
|
rhash_md5_process_block(ctx->hash, aligned_message_block); |
|
193
|
0
|
|
|
|
|
|
msg += md5_block_size; |
|
194
|
0
|
|
|
|
|
|
size -= md5_block_size; |
|
195
|
|
|
|
|
|
|
} |
|
196
|
7
|
50
|
|
|
|
|
if (size) { |
|
197
|
|
|
|
|
|
|
/* save leftovers */ |
|
198
|
7
|
|
|
|
|
|
le32_copy(ctx->message, 0, msg, size); |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
/** |
|
203
|
|
|
|
|
|
|
* Store calculated hash into the given array. |
|
204
|
|
|
|
|
|
|
* |
|
205
|
|
|
|
|
|
|
* @param ctx the algorithm context containing current hashing state |
|
206
|
|
|
|
|
|
|
* @param result calculated hash in binary form |
|
207
|
|
|
|
|
|
|
*/ |
|
208
|
8
|
|
|
|
|
|
void rhash_md5_final(md5_ctx *ctx, unsigned char* result) |
|
209
|
|
|
|
|
|
|
{ |
|
210
|
8
|
|
|
|
|
|
unsigned index = ((unsigned)ctx->length & 63) >> 2; |
|
211
|
8
|
|
|
|
|
|
unsigned shift = ((unsigned)ctx->length & 3) * 8; |
|
212
|
|
|
|
|
|
|
|
|
213
|
|
|
|
|
|
|
/* pad message and run for last block */ |
|
214
|
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
/* append the byte 0x80 to the message */ |
|
216
|
8
|
|
|
|
|
|
ctx->message[index] &= ~(0xFFFFFFFFu << shift); |
|
217
|
8
|
|
|
|
|
|
ctx->message[index++] ^= 0x80u << shift; |
|
218
|
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
/* if no room left in the message to store 64-bit message length */ |
|
220
|
8
|
50
|
|
|
|
|
if (index > 14) { |
|
221
|
|
|
|
|
|
|
/* then fill the rest with zeros and process it */ |
|
222
|
0
|
0
|
|
|
|
|
while (index < 16) { |
|
223
|
0
|
|
|
|
|
|
ctx->message[index++] = 0; |
|
224
|
|
|
|
|
|
|
} |
|
225
|
0
|
|
|
|
|
|
rhash_md5_process_block(ctx->hash, ctx->message); |
|
226
|
0
|
|
|
|
|
|
index = 0; |
|
227
|
|
|
|
|
|
|
} |
|
228
|
100
|
100
|
|
|
|
|
while (index < 14) { |
|
229
|
92
|
|
|
|
|
|
ctx->message[index++] = 0; |
|
230
|
|
|
|
|
|
|
} |
|
231
|
8
|
|
|
|
|
|
ctx->message[14] = (unsigned)(ctx->length << 3); |
|
232
|
8
|
|
|
|
|
|
ctx->message[15] = (unsigned)(ctx->length >> 29); |
|
233
|
8
|
|
|
|
|
|
rhash_md5_process_block(ctx->hash, ctx->message); |
|
234
|
|
|
|
|
|
|
|
|
235
|
8
|
50
|
|
|
|
|
if (result) le32_copy(result, 0, &ctx->hash, 16); |
|
236
|
8
|
|
|
|
|
|
} |