line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* md5.c - an implementation of the MD5 algorithm, based on RFC 1321. |
2
|
|
|
|
|
|
|
* |
3
|
|
|
|
|
|
|
* Copyright (c) 2007, Aleksey Kravchenko |
4
|
|
|
|
|
|
|
* |
5
|
|
|
|
|
|
|
* Permission to use, copy, modify, and/or distribute this software for any |
6
|
|
|
|
|
|
|
* purpose with or without fee is hereby granted. |
7
|
|
|
|
|
|
|
* |
8
|
|
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
9
|
|
|
|
|
|
|
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
10
|
|
|
|
|
|
|
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
11
|
|
|
|
|
|
|
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
12
|
|
|
|
|
|
|
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
13
|
|
|
|
|
|
|
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
14
|
|
|
|
|
|
|
* PERFORMANCE OF THIS SOFTWARE. |
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
|
|
|
|
|
|
} |