| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
/* |
|
2
|
|
|
|
|
|
|
* pdfmake_md5.c — MD5 hash implementation |
|
3
|
|
|
|
|
|
|
* |
|
4
|
|
|
|
|
|
|
* Reference implementation per RFC 1321. |
|
5
|
|
|
|
|
|
|
* Required for PDF encryption key derivation (R2-R4). |
|
6
|
|
|
|
|
|
|
*/ |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
#include "pdfmake_md5.h" |
|
9
|
|
|
|
|
|
|
#include |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
/*============================================================================ |
|
12
|
|
|
|
|
|
|
* MD5 constants |
|
13
|
|
|
|
|
|
|
*==========================================================================*/ |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
/* Initial hash values */ |
|
16
|
|
|
|
|
|
|
#define MD5_A0 0x67452301 |
|
17
|
|
|
|
|
|
|
#define MD5_B0 0xefcdab89 |
|
18
|
|
|
|
|
|
|
#define MD5_C0 0x98badcfe |
|
19
|
|
|
|
|
|
|
#define MD5_D0 0x10325476 |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
/* Per-round shift amounts */ |
|
22
|
|
|
|
|
|
|
static const uint8_t S[64] = { |
|
23
|
|
|
|
|
|
|
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, |
|
24
|
|
|
|
|
|
|
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, |
|
25
|
|
|
|
|
|
|
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, |
|
26
|
|
|
|
|
|
|
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 |
|
27
|
|
|
|
|
|
|
}; |
|
28
|
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
/* Pre-computed K values: floor(2^32 * abs(sin(i+1))) */ |
|
30
|
|
|
|
|
|
|
static const uint32_t K[64] = { |
|
31
|
|
|
|
|
|
|
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, |
|
32
|
|
|
|
|
|
|
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, |
|
33
|
|
|
|
|
|
|
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, |
|
34
|
|
|
|
|
|
|
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, |
|
35
|
|
|
|
|
|
|
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, |
|
36
|
|
|
|
|
|
|
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, |
|
37
|
|
|
|
|
|
|
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, |
|
38
|
|
|
|
|
|
|
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, |
|
39
|
|
|
|
|
|
|
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, |
|
40
|
|
|
|
|
|
|
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, |
|
41
|
|
|
|
|
|
|
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, |
|
42
|
|
|
|
|
|
|
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, |
|
43
|
|
|
|
|
|
|
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, |
|
44
|
|
|
|
|
|
|
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, |
|
45
|
|
|
|
|
|
|
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, |
|
46
|
|
|
|
|
|
|
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 |
|
47
|
|
|
|
|
|
|
}; |
|
48
|
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
/*============================================================================ |
|
50
|
|
|
|
|
|
|
* Helper macros |
|
51
|
|
|
|
|
|
|
*==========================================================================*/ |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
#define ROTL32(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
#define F(x, y, z) (((x) & (y)) | ((~(x)) & (z))) |
|
56
|
|
|
|
|
|
|
#define G(x, y, z) (((x) & (z)) | ((y) & (~(z)))) |
|
57
|
|
|
|
|
|
|
#define H(x, y, z) ((x) ^ (y) ^ (z)) |
|
58
|
|
|
|
|
|
|
#define I(x, y, z) ((y) ^ ((x) | (~(z)))) |
|
59
|
|
|
|
|
|
|
|
|
60
|
43232
|
|
|
|
|
|
static PDFMAKE_INLINE uint32_t read_le32(const uint8_t *p) |
|
61
|
|
|
|
|
|
|
{ |
|
62
|
43232
|
|
|
|
|
|
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | |
|
63
|
43232
|
|
|
|
|
|
((uint32_t)p[2] << 16) | ((uint32_t)p[3] << 24); |
|
64
|
|
|
|
|
|
|
} |
|
65
|
|
|
|
|
|
|
|
|
66
|
10556
|
|
|
|
|
|
static PDFMAKE_INLINE void write_le32(uint8_t *p, uint32_t x) |
|
67
|
|
|
|
|
|
|
{ |
|
68
|
10556
|
|
|
|
|
|
p[0] = (uint8_t)(x); |
|
69
|
10556
|
|
|
|
|
|
p[1] = (uint8_t)(x >> 8); |
|
70
|
10556
|
|
|
|
|
|
p[2] = (uint8_t)(x >> 16); |
|
71
|
10556
|
|
|
|
|
|
p[3] = (uint8_t)(x >> 24); |
|
72
|
10556
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
2639
|
|
|
|
|
|
static PDFMAKE_INLINE void write_le64(uint8_t *p, uint64_t x) |
|
75
|
|
|
|
|
|
|
{ |
|
76
|
2639
|
|
|
|
|
|
p[0] = (uint8_t)(x); |
|
77
|
2639
|
|
|
|
|
|
p[1] = (uint8_t)(x >> 8); |
|
78
|
2639
|
|
|
|
|
|
p[2] = (uint8_t)(x >> 16); |
|
79
|
2639
|
|
|
|
|
|
p[3] = (uint8_t)(x >> 24); |
|
80
|
2639
|
|
|
|
|
|
p[4] = (uint8_t)(x >> 32); |
|
81
|
2639
|
|
|
|
|
|
p[5] = (uint8_t)(x >> 40); |
|
82
|
2639
|
|
|
|
|
|
p[6] = (uint8_t)(x >> 48); |
|
83
|
2639
|
|
|
|
|
|
p[7] = (uint8_t)(x >> 56); |
|
84
|
2639
|
|
|
|
|
|
} |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
/*============================================================================ |
|
87
|
|
|
|
|
|
|
* MD5 transform (process one 64-byte block) |
|
88
|
|
|
|
|
|
|
*==========================================================================*/ |
|
89
|
|
|
|
|
|
|
|
|
90
|
2702
|
|
|
|
|
|
static void md5_transform(uint32_t state[4], const uint8_t block[64]) |
|
91
|
|
|
|
|
|
|
{ |
|
92
|
2702
|
|
|
|
|
|
uint32_t a = state[0]; |
|
93
|
2702
|
|
|
|
|
|
uint32_t b = state[1]; |
|
94
|
2702
|
|
|
|
|
|
uint32_t c = state[2]; |
|
95
|
2702
|
|
|
|
|
|
uint32_t d = state[3]; |
|
96
|
|
|
|
|
|
|
uint32_t M[16]; |
|
97
|
|
|
|
|
|
|
int i; |
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
/* Decode 64 bytes into 16 little-endian 32-bit words */ |
|
100
|
45934
|
100
|
|
|
|
|
for (i = 0; i < 16; i++) { |
|
101
|
43232
|
|
|
|
|
|
M[i] = read_le32(block + i * 4); |
|
102
|
|
|
|
|
|
|
} |
|
103
|
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
/* 64 rounds */ |
|
105
|
175630
|
100
|
|
|
|
|
for (i = 0; i < 64; i++) { |
|
106
|
|
|
|
|
|
|
uint32_t f, g; |
|
107
|
|
|
|
|
|
|
|
|
108
|
172928
|
100
|
|
|
|
|
if (i < 16) { |
|
109
|
43232
|
|
|
|
|
|
f = F(b, c, d); |
|
110
|
43232
|
|
|
|
|
|
g = i; |
|
111
|
129696
|
100
|
|
|
|
|
} else if (i < 32) { |
|
112
|
43232
|
|
|
|
|
|
f = G(b, c, d); |
|
113
|
43232
|
|
|
|
|
|
g = (5 * i + 1) % 16; |
|
114
|
86464
|
100
|
|
|
|
|
} else if (i < 48) { |
|
115
|
43232
|
|
|
|
|
|
f = H(b, c, d); |
|
116
|
43232
|
|
|
|
|
|
g = (3 * i + 5) % 16; |
|
117
|
|
|
|
|
|
|
} else { |
|
118
|
43232
|
|
|
|
|
|
f = I(b, c, d); |
|
119
|
43232
|
|
|
|
|
|
g = (7 * i) % 16; |
|
120
|
|
|
|
|
|
|
} |
|
121
|
|
|
|
|
|
|
|
|
122
|
172928
|
|
|
|
|
|
f = f + a + K[i] + M[g]; |
|
123
|
172928
|
|
|
|
|
|
a = d; |
|
124
|
172928
|
|
|
|
|
|
d = c; |
|
125
|
172928
|
|
|
|
|
|
c = b; |
|
126
|
172928
|
|
|
|
|
|
b = b + ROTL32(f, S[i]); |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
|
|
129
|
2702
|
|
|
|
|
|
state[0] += a; |
|
130
|
2702
|
|
|
|
|
|
state[1] += b; |
|
131
|
2702
|
|
|
|
|
|
state[2] += c; |
|
132
|
2702
|
|
|
|
|
|
state[3] += d; |
|
133
|
2702
|
|
|
|
|
|
} |
|
134
|
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
/*============================================================================ |
|
136
|
|
|
|
|
|
|
* Public API |
|
137
|
|
|
|
|
|
|
*==========================================================================*/ |
|
138
|
|
|
|
|
|
|
|
|
139
|
2639
|
|
|
|
|
|
void pdfmake_md5_init(pdfmake_md5_ctx_t *ctx) |
|
140
|
|
|
|
|
|
|
{ |
|
141
|
2639
|
|
|
|
|
|
ctx->state[0] = MD5_A0; |
|
142
|
2639
|
|
|
|
|
|
ctx->state[1] = MD5_B0; |
|
143
|
2639
|
|
|
|
|
|
ctx->state[2] = MD5_C0; |
|
144
|
2639
|
|
|
|
|
|
ctx->state[3] = MD5_D0; |
|
145
|
2639
|
|
|
|
|
|
ctx->count = 0; |
|
146
|
2639
|
|
|
|
|
|
memset(ctx->buffer, 0, sizeof(ctx->buffer)); |
|
147
|
2639
|
|
|
|
|
|
} |
|
148
|
|
|
|
|
|
|
|
|
149
|
8251
|
|
|
|
|
|
void pdfmake_md5_update(pdfmake_md5_ctx_t *ctx, const uint8_t *data, size_t len) |
|
150
|
|
|
|
|
|
|
{ |
|
151
|
8251
|
|
|
|
|
|
size_t buf_pos = (ctx->count / 8) % 64; |
|
152
|
8251
|
|
|
|
|
|
ctx->count += (uint64_t)len * 8; |
|
153
|
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
/* If we have buffered data and new data fills the buffer */ |
|
155
|
8251
|
100
|
|
|
|
|
if (buf_pos > 0) { |
|
156
|
5549
|
|
|
|
|
|
size_t space = 64 - buf_pos; |
|
157
|
5549
|
100
|
|
|
|
|
if (len >= space) { |
|
158
|
2702
|
|
|
|
|
|
memcpy(ctx->buffer + buf_pos, data, space); |
|
159
|
2702
|
|
|
|
|
|
md5_transform(ctx->state, ctx->buffer); |
|
160
|
2702
|
|
|
|
|
|
data += space; |
|
161
|
2702
|
|
|
|
|
|
len -= space; |
|
162
|
2702
|
|
|
|
|
|
buf_pos = 0; |
|
163
|
|
|
|
|
|
|
} else { |
|
164
|
2847
|
|
|
|
|
|
memcpy(ctx->buffer + buf_pos, data, len); |
|
165
|
2847
|
|
|
|
|
|
return; |
|
166
|
|
|
|
|
|
|
} |
|
167
|
|
|
|
|
|
|
} |
|
168
|
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
/* Process full blocks */ |
|
170
|
5404
|
50
|
|
|
|
|
while (len >= 64) { |
|
171
|
0
|
|
|
|
|
|
md5_transform(ctx->state, data); |
|
172
|
0
|
|
|
|
|
|
data += 64; |
|
173
|
0
|
|
|
|
|
|
len -= 64; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
/* Buffer remaining data */ |
|
177
|
5404
|
100
|
|
|
|
|
if (len > 0) { |
|
178
|
2702
|
|
|
|
|
|
memcpy(ctx->buffer, data, len); |
|
179
|
|
|
|
|
|
|
} |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
|
|
182
|
2639
|
|
|
|
|
|
void pdfmake_md5_final(pdfmake_md5_ctx_t *ctx, uint8_t digest[16]) |
|
183
|
|
|
|
|
|
|
{ |
|
184
|
2639
|
|
|
|
|
|
uint64_t bits = ctx->count; |
|
185
|
2639
|
|
|
|
|
|
size_t buf_pos = (bits / 8) % 64; |
|
186
|
|
|
|
|
|
|
size_t pad_len; |
|
187
|
|
|
|
|
|
|
uint8_t pad[64]; |
|
188
|
|
|
|
|
|
|
uint8_t len_bytes[8]; |
|
189
|
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
/* Padding: append 0x80 then zeros, leaving 8 bytes for length */ |
|
191
|
2639
|
|
|
|
|
|
memset(pad, 0, sizeof(pad)); |
|
192
|
2639
|
|
|
|
|
|
pad[0] = 0x80; |
|
193
|
|
|
|
|
|
|
|
|
194
|
2639
|
50
|
|
|
|
|
pad_len = (buf_pos < 56) ? (56 - buf_pos) : (120 - buf_pos); |
|
195
|
2639
|
|
|
|
|
|
pdfmake_md5_update(ctx, pad, pad_len); |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
/* Append original length in bits as 64-bit little-endian */ |
|
198
|
2639
|
|
|
|
|
|
write_le64(len_bytes, bits); |
|
199
|
2639
|
|
|
|
|
|
pdfmake_md5_update(ctx, len_bytes, 8); |
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
/* Output digest */ |
|
202
|
2639
|
|
|
|
|
|
write_le32(digest + 0, ctx->state[0]); |
|
203
|
2639
|
|
|
|
|
|
write_le32(digest + 4, ctx->state[1]); |
|
204
|
2639
|
|
|
|
|
|
write_le32(digest + 8, ctx->state[2]); |
|
205
|
2639
|
|
|
|
|
|
write_le32(digest + 12, ctx->state[3]); |
|
206
|
2639
|
|
|
|
|
|
} |
|
207
|
|
|
|
|
|
|
|
|
208
|
2439
|
|
|
|
|
|
void pdfmake_md5(const uint8_t *data, size_t len, uint8_t digest[16]) |
|
209
|
|
|
|
|
|
|
{ |
|
210
|
|
|
|
|
|
|
pdfmake_md5_ctx_t ctx; |
|
211
|
2439
|
|
|
|
|
|
pdfmake_md5_init(&ctx); |
|
212
|
2439
|
|
|
|
|
|
pdfmake_md5_update(&ctx, data, len); |
|
213
|
2439
|
|
|
|
|
|
pdfmake_md5_final(&ctx, digest); |
|
214
|
2439
|
|
|
|
|
|
} |