| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#ifndef HORUS_MD5_H |
|
2
|
|
|
|
|
|
|
#define HORUS_MD5_H |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
/* |
|
5
|
|
|
|
|
|
|
* horus_md5.h - Minimal embedded MD5 implementation (RFC 1321) |
|
6
|
|
|
|
|
|
|
* |
|
7
|
|
|
|
|
|
|
* Self-contained, no external dependencies. All functions static |
|
8
|
|
|
|
|
|
|
* to avoid symbol conflicts with system MD5. |
|
9
|
|
|
|
|
|
|
*/ |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
#include |
|
12
|
|
|
|
|
|
|
#include |
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
typedef struct { |
|
15
|
|
|
|
|
|
|
uint32_t state[4]; |
|
16
|
|
|
|
|
|
|
uint64_t count; |
|
17
|
|
|
|
|
|
|
unsigned char buffer[64]; |
|
18
|
|
|
|
|
|
|
} horus_md5_ctx; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
#define HORUS_MD5_F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) |
|
21
|
|
|
|
|
|
|
#define HORUS_MD5_G(x, y, z) (((x) & (z)) | ((y) & (~(z)))) |
|
22
|
|
|
|
|
|
|
#define HORUS_MD5_HH(x, y, z) ((x) ^ (y) ^ (z)) |
|
23
|
|
|
|
|
|
|
#define HORUS_MD5_I(x, y, z) ((y) ^ ((x) | (~(z)))) |
|
24
|
|
|
|
|
|
|
#define HORUS_MD5_ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
#define HORUS_MD5_STEP(f, a, b, c, d, x, t, s) \ |
|
27
|
|
|
|
|
|
|
(a) += f((b), (c), (d)) + (x) + (t); \ |
|
28
|
|
|
|
|
|
|
(a) = HORUS_MD5_ROTL((a), (s)); \ |
|
29
|
|
|
|
|
|
|
(a) += (b) |
|
30
|
|
|
|
|
|
|
|
|
31
|
0
|
|
|
|
|
|
static inline uint32_t horus_md5_decode32(const unsigned char *p) { |
|
32
|
0
|
|
|
|
|
|
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) |
|
33
|
0
|
|
|
|
|
|
| ((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); |
|
34
|
|
|
|
|
|
|
} |
|
35
|
|
|
|
|
|
|
|
|
36
|
0
|
|
|
|
|
|
static void horus_md5_transform(uint32_t state[4], const unsigned char block[64]) { |
|
37
|
0
|
|
|
|
|
|
uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; |
|
38
|
|
|
|
|
|
|
uint32_t M[16]; |
|
39
|
|
|
|
|
|
|
int i; |
|
40
|
|
|
|
|
|
|
|
|
41
|
0
|
0
|
|
|
|
|
for (i = 0; i < 16; i++) |
|
42
|
0
|
|
|
|
|
|
M[i] = horus_md5_decode32(block + i * 4); |
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
/* Round 1 */ |
|
45
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, a, b, c, d, M[ 0], 0xd76aa478, 7); |
|
46
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, d, a, b, c, M[ 1], 0xe8c7b756, 12); |
|
47
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, c, d, a, b, M[ 2], 0x242070db, 17); |
|
48
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, b, c, d, a, M[ 3], 0xc1bdceee, 22); |
|
49
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, a, b, c, d, M[ 4], 0xf57c0faf, 7); |
|
50
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, d, a, b, c, M[ 5], 0x4787c62a, 12); |
|
51
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, c, d, a, b, M[ 6], 0xa8304613, 17); |
|
52
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, b, c, d, a, M[ 7], 0xfd469501, 22); |
|
53
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, a, b, c, d, M[ 8], 0x698098d8, 7); |
|
54
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, d, a, b, c, M[ 9], 0x8b44f7af, 12); |
|
55
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, c, d, a, b, M[10], 0xffff5bb1, 17); |
|
56
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, b, c, d, a, M[11], 0x895cd7be, 22); |
|
57
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, a, b, c, d, M[12], 0x6b901122, 7); |
|
58
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, d, a, b, c, M[13], 0xfd987193, 12); |
|
59
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, c, d, a, b, M[14], 0xa679438e, 17); |
|
60
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_F, b, c, d, a, M[15], 0x49b40821, 22); |
|
61
|
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
/* Round 2 */ |
|
63
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, a, b, c, d, M[ 1], 0xf61e2562, 5); |
|
64
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, d, a, b, c, M[ 6], 0xc040b340, 9); |
|
65
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, c, d, a, b, M[11], 0x265e5a51, 14); |
|
66
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, b, c, d, a, M[ 0], 0xe9b6c7aa, 20); |
|
67
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, a, b, c, d, M[ 5], 0xd62f105d, 5); |
|
68
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, d, a, b, c, M[10], 0x02441453, 9); |
|
69
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, c, d, a, b, M[15], 0xd8a1e681, 14); |
|
70
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, b, c, d, a, M[ 4], 0xe7d3fbc8, 20); |
|
71
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, a, b, c, d, M[ 9], 0x21e1cde6, 5); |
|
72
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, d, a, b, c, M[14], 0xc33707d6, 9); |
|
73
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, c, d, a, b, M[ 3], 0xf4d50d87, 14); |
|
74
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, b, c, d, a, M[ 8], 0x455a14ed, 20); |
|
75
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, a, b, c, d, M[13], 0xa9e3e905, 5); |
|
76
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, d, a, b, c, M[ 2], 0xfcefa3f8, 9); |
|
77
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, c, d, a, b, M[ 7], 0x676f02d9, 14); |
|
78
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_G, b, c, d, a, M[12], 0x8d2a4c8a, 20); |
|
79
|
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
/* Round 3 */ |
|
81
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, a, b, c, d, M[ 5], 0xfffa3942, 4); |
|
82
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, d, a, b, c, M[ 8], 0x8771f681, 11); |
|
83
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, c, d, a, b, M[11], 0x6d9d6122, 16); |
|
84
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, b, c, d, a, M[14], 0xfde5380c, 23); |
|
85
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, a, b, c, d, M[ 1], 0xa4beea44, 4); |
|
86
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, d, a, b, c, M[ 4], 0x4bdecfa9, 11); |
|
87
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, c, d, a, b, M[ 7], 0xf6bb4b60, 16); |
|
88
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, b, c, d, a, M[10], 0xbebfbc70, 23); |
|
89
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, a, b, c, d, M[13], 0x289b7ec6, 4); |
|
90
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, d, a, b, c, M[ 0], 0xeaa127fa, 11); |
|
91
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, c, d, a, b, M[ 3], 0xd4ef3085, 16); |
|
92
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, b, c, d, a, M[ 6], 0x04881d05, 23); |
|
93
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, a, b, c, d, M[ 9], 0xd9d4d039, 4); |
|
94
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, d, a, b, c, M[12], 0xe6db99e5, 11); |
|
95
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, c, d, a, b, M[15], 0x1fa27cf8, 16); |
|
96
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_HH, b, c, d, a, M[ 2], 0xc4ac5665, 23); |
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
/* Round 4 */ |
|
99
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, a, b, c, d, M[ 0], 0xf4292244, 6); |
|
100
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, d, a, b, c, M[ 7], 0x432aff97, 10); |
|
101
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, c, d, a, b, M[14], 0xab9423a7, 15); |
|
102
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, b, c, d, a, M[ 5], 0xfc93a039, 21); |
|
103
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, a, b, c, d, M[12], 0x655b59c3, 6); |
|
104
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, d, a, b, c, M[ 3], 0x8f0ccc92, 10); |
|
105
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, c, d, a, b, M[10], 0xffeff47d, 15); |
|
106
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, b, c, d, a, M[ 1], 0x85845dd1, 21); |
|
107
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, a, b, c, d, M[ 8], 0x6fa87e4f, 6); |
|
108
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, d, a, b, c, M[15], 0xfe2ce6e0, 10); |
|
109
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, c, d, a, b, M[ 6], 0xa3014314, 15); |
|
110
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, b, c, d, a, M[13], 0x4e0811a1, 21); |
|
111
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, a, b, c, d, M[ 4], 0xf7537e82, 6); |
|
112
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, d, a, b, c, M[11], 0xbd3af235, 10); |
|
113
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, c, d, a, b, M[ 2], 0x2ad7d2bb, 15); |
|
114
|
0
|
|
|
|
|
|
HORUS_MD5_STEP(HORUS_MD5_I, b, c, d, a, M[ 9], 0xeb86d391, 21); |
|
115
|
|
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
|
state[0] += a; |
|
117
|
0
|
|
|
|
|
|
state[1] += b; |
|
118
|
0
|
|
|
|
|
|
state[2] += c; |
|
119
|
0
|
|
|
|
|
|
state[3] += d; |
|
120
|
0
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
static inline void horus_md5_init(horus_md5_ctx *ctx) { |
|
123
|
|
|
|
|
|
|
ctx->count = 0; |
|
124
|
|
|
|
|
|
|
ctx->state[0] = 0x67452301; |
|
125
|
|
|
|
|
|
|
ctx->state[1] = 0xefcdab89; |
|
126
|
|
|
|
|
|
|
ctx->state[2] = 0x98badcfe; |
|
127
|
|
|
|
|
|
|
ctx->state[3] = 0x10325476; |
|
128
|
|
|
|
|
|
|
} |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
static inline void horus_md5_update(horus_md5_ctx *ctx, |
|
131
|
|
|
|
|
|
|
const unsigned char *data, size_t len) { |
|
132
|
|
|
|
|
|
|
size_t index = (size_t)(ctx->count & 0x3F); |
|
133
|
|
|
|
|
|
|
ctx->count += len; |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
if (index) { |
|
136
|
|
|
|
|
|
|
size_t part_len = 64 - index; |
|
137
|
|
|
|
|
|
|
if (len >= part_len) { |
|
138
|
|
|
|
|
|
|
memcpy(ctx->buffer + index, data, part_len); |
|
139
|
|
|
|
|
|
|
horus_md5_transform(ctx->state, ctx->buffer); |
|
140
|
|
|
|
|
|
|
data += part_len; |
|
141
|
|
|
|
|
|
|
len -= part_len; |
|
142
|
|
|
|
|
|
|
} else { |
|
143
|
|
|
|
|
|
|
memcpy(ctx->buffer + index, data, len); |
|
144
|
|
|
|
|
|
|
return; |
|
145
|
|
|
|
|
|
|
} |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
while (len >= 64) { |
|
149
|
|
|
|
|
|
|
horus_md5_transform(ctx->state, data); |
|
150
|
|
|
|
|
|
|
data += 64; |
|
151
|
|
|
|
|
|
|
len -= 64; |
|
152
|
|
|
|
|
|
|
} |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
if (len) |
|
155
|
|
|
|
|
|
|
memcpy(ctx->buffer, data, len); |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
static inline void horus_md5_final(unsigned char digest[16], horus_md5_ctx *ctx) { |
|
159
|
|
|
|
|
|
|
static const unsigned char padding[64] = { 0x80 }; |
|
160
|
|
|
|
|
|
|
unsigned char bits[8]; |
|
161
|
|
|
|
|
|
|
uint64_t bit_count = ctx->count << 3; |
|
162
|
|
|
|
|
|
|
size_t index; |
|
163
|
|
|
|
|
|
|
int i; |
|
164
|
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
/* Encode bit count as little-endian */ |
|
166
|
|
|
|
|
|
|
for (i = 0; i < 8; i++) |
|
167
|
|
|
|
|
|
|
bits[i] = (unsigned char)(bit_count >> (i * 8)); |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
/* Pad to 56 mod 64 */ |
|
170
|
|
|
|
|
|
|
index = (size_t)(ctx->count & 0x3F); |
|
171
|
|
|
|
|
|
|
horus_md5_update(ctx, padding, (index < 56) ? (56 - index) : (120 - index)); |
|
172
|
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
/* Append length */ |
|
174
|
|
|
|
|
|
|
horus_md5_update(ctx, bits, 8); |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
/* Encode state as little-endian */ |
|
177
|
|
|
|
|
|
|
for (i = 0; i < 4; i++) { |
|
178
|
|
|
|
|
|
|
digest[i*4 + 0] = (unsigned char)(ctx->state[i]); |
|
179
|
|
|
|
|
|
|
digest[i*4 + 1] = (unsigned char)(ctx->state[i] >> 8); |
|
180
|
|
|
|
|
|
|
digest[i*4 + 2] = (unsigned char)(ctx->state[i] >> 16); |
|
181
|
|
|
|
|
|
|
digest[i*4 + 3] = (unsigned char)(ctx->state[i] >> 24); |
|
182
|
|
|
|
|
|
|
} |
|
183
|
|
|
|
|
|
|
} |
|
184
|
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
/* Convenience: hash data in one shot */ |
|
186
|
|
|
|
|
|
|
static inline void horus_md5(unsigned char digest[16], |
|
187
|
|
|
|
|
|
|
const unsigned char *data, size_t len) { |
|
188
|
|
|
|
|
|
|
horus_md5_ctx ctx; |
|
189
|
|
|
|
|
|
|
horus_md5_init(&ctx); |
|
190
|
|
|
|
|
|
|
horus_md5_update(&ctx, data, len); |
|
191
|
|
|
|
|
|
|
horus_md5_final(digest, &ctx); |
|
192
|
|
|
|
|
|
|
} |
|
193
|
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
#endif /* HORUS_MD5_H */ |