Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/crypto/md5c.c
48033 views
1
/*-
2
* Copyright (c) 2024, 2025 Robert Clausecker <[email protected]>
3
*
4
* SPDX-License-Identifier: BSD-2-Clause
5
*/
6
7
#include <sys/endian.h>
8
#include <sys/types.h>
9
#include <sys/md5.h>
10
11
#ifdef _KERNEL
12
#include <sys/param.h>
13
#include <sys/stdint.h>
14
#include <sys/systm.h>
15
#define assert(expr) MPASS(expr)
16
#else
17
#include <assert.h>
18
#include <stdint.h>
19
#include <string.h>
20
#include <strings.h>
21
#endif /* defined(_KERNEL) */
22
23
#define md5block _libmd_md5block
24
#ifdef MD5_ASM
25
extern void md5block(MD5_CTX *, const void *, size_t);
26
#else
27
static void md5block(MD5_CTX *, const void *, size_t);
28
#endif
29
30
/* don't unroll in bootloader */
31
#ifdef STANDALONE_SMALL
32
#define UNROLL
33
#else
34
#define UNROLL _Pragma("unroll")
35
#endif
36
37
void
38
MD5Init(MD5_CTX *ctx)
39
{
40
ctx->state[0] = 0x67452301;
41
ctx->state[1] = 0xefcdab89;
42
ctx->state[2] = 0x98badcfe;
43
ctx->state[3] = 0x10325476;
44
45
ctx->count[0] = 0;
46
ctx->count[1] = 0;
47
}
48
49
void
50
MD5Update(MD5_CTX *ctx, const void *data, unsigned int len)
51
{
52
uint64_t nn;
53
const char *p = data;
54
unsigned num;
55
56
num = ctx->count[0] % MD5_BLOCK_LENGTH;
57
nn = (uint64_t)ctx->count[0] | (uint64_t)ctx->count[1] << 32;
58
nn += len;
59
ctx->count[0] = (uint32_t)nn;
60
ctx->count[1] = (uint32_t)(nn >> 32);
61
62
if (num > 0) {
63
unsigned int n = MD5_BLOCK_LENGTH - num;
64
65
if (n > len)
66
n = len;
67
68
memcpy((char *)ctx->buffer + num, p, n);
69
num += n;
70
if (num == MD5_BLOCK_LENGTH)
71
md5block(ctx, (void *)ctx->buffer, MD5_BLOCK_LENGTH);
72
73
p += n;
74
len -= n;
75
}
76
77
if (len >= MD5_BLOCK_LENGTH) {
78
unsigned n = len & ~(unsigned)(MD5_BLOCK_LENGTH - 1);
79
80
md5block(ctx, p, n);
81
p += n;
82
len -= n;
83
}
84
85
if (len > 0)
86
memcpy((void *)ctx->buffer, p, len);
87
}
88
89
static void
90
MD5Pad(MD5_CTX *ctx)
91
{
92
uint64_t len;
93
unsigned t;
94
unsigned char tmp[MD5_BLOCK_LENGTH + sizeof(uint64_t)] = {0x80, 0};
95
96
len = (uint64_t)ctx->count[0] | (uint64_t)ctx->count[1] << 32;
97
t = 64 + 56 - ctx->count[0] % 64;
98
if (t > 64)
99
t -= 64;
100
101
/* length in bits */
102
len <<= 3;
103
le64enc(tmp + t, len);
104
MD5Update(ctx, tmp, t + 8);
105
assert(ctx->count[0] % MD5_BLOCK_LENGTH == 0);
106
}
107
108
void
109
MD5Final(unsigned char md[16], MD5_CTX *ctx)
110
{
111
MD5Pad(ctx);
112
113
le32enc(md + 0, ctx->state[0]);
114
le32enc(md + 4, ctx->state[1]);
115
le32enc(md + 8, ctx->state[2]);
116
le32enc(md + 12, ctx->state[3]);
117
118
explicit_bzero(ctx, sizeof(ctx));
119
}
120
121
#ifndef MD5_ASM
122
static const uint32_t K[64] = {
123
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
124
0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
125
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
126
0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
127
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
128
0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
129
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
130
0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
131
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
132
0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
133
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
134
0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
135
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
136
0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
137
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
138
0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
139
};
140
141
static inline uint32_t
142
rol32(uint32_t a, int b)
143
{
144
return (a << b | a >> (32 - b));
145
}
146
147
static void
148
md5block(MD5_CTX *ctx, const void *data, size_t len)
149
{
150
uint32_t m[16], a0, b0, c0, d0;
151
const char *p = data;
152
153
a0 = ctx->state[0];
154
b0 = ctx->state[1];
155
c0 = ctx->state[2];
156
d0 = ctx->state[3];
157
158
while (len >= MD5_BLOCK_LENGTH) {
159
size_t i;
160
uint32_t a = a0, b = b0, c = c0, d = d0, f, tmp;
161
162
UNROLL
163
for (i = 0; i < 16; i++)
164
m[i] = le32dec(p + 4*i);
165
166
UNROLL
167
for (i = 0; i < 16; i += 4) {
168
f = d ^ (b & (c ^ d));
169
tmp = d;
170
d = c;
171
c = b;
172
b += rol32(a + f + K[i] + m[i], 7);
173
a = tmp;
174
175
f = d ^ (b & (c ^ d));
176
tmp = d;
177
d = c;
178
c = b;
179
b += rol32(a + f + K[i + 1] + m[i + 1], 12);
180
a = tmp;
181
182
f = d ^ (b & (c ^ d));
183
tmp = d;
184
d = c;
185
c = b;
186
b += rol32(a + f + K[i + 2] + m[i + 2], 17);
187
a = tmp;
188
189
f = d ^ (b & (c ^ d));
190
tmp = d;
191
d = c;
192
c = b;
193
b += rol32(a + f + K[i + 3] + m[i + 3], 22);
194
a = tmp;
195
}
196
197
UNROLL
198
for (; i < 32; i += 4) {
199
f = c ^ (d & (b ^ c));
200
tmp = d;
201
d = c;
202
c = b;
203
b += rol32(a + f + K[i] + m[(5*i + 1) % 16], 5);
204
a = tmp;
205
206
f = c ^ (d & (b ^ c));
207
tmp = d;
208
d = c;
209
c = b;
210
b += rol32(a + f + K[i + 1] + m[(5*i + 6) % 16], 9);
211
a = tmp;
212
213
f = c ^ (d & (b ^ c));
214
tmp = d;
215
d = c;
216
c = b;
217
b += rol32(a + f + K[i + 2] + m[(5*i + 11) % 16], 14);
218
a = tmp;
219
220
f = c ^ (d & (b ^ c));
221
tmp = d;
222
d = c;
223
c = b;
224
b += rol32(a + f + K[i + 3] + m[5*i % 16], 20);
225
a = tmp;
226
}
227
228
UNROLL
229
for (; i < 48; i += 4) {
230
f = b ^ c ^ d;
231
tmp = d;
232
d = c;
233
c = b;
234
b += rol32(a + f + K[i] + m[(3*i + 5) % 16], 4);
235
a = tmp;
236
237
f = b ^ c ^ d;
238
tmp = d;
239
d = c;
240
c = b;
241
b += rol32(a + f + K[i + 1] + m[(3*i + 8) % 16], 11);
242
a = tmp;
243
244
f = b ^ c ^ d;
245
tmp = d;
246
d = c;
247
c = b;
248
b += rol32(a + f + K[i + 2] + m[(3*i + 11) % 16], 16);
249
a = tmp;
250
251
f = b ^ c ^ d;
252
tmp = d;
253
d = c;
254
c = b;
255
b += rol32(a + f + K[i + 3] + m[(3*i + 14) % 16], 23);
256
a = tmp;
257
}
258
259
UNROLL
260
for (; i < 64; i += 4) {
261
f = c ^ (b | ~d);
262
tmp = d;
263
d = c;
264
c = b;
265
b += rol32(a + f + K[i] + m[7*i % 16], 6);
266
a = tmp;
267
268
f = c ^ (b | ~d);
269
tmp = d;
270
d = c;
271
c = b;
272
b += rol32(a + f + K[i + 1] + m[(7*i + 7) % 16], 10);
273
a = tmp;
274
275
f = c ^ (b | ~d);
276
tmp = d;
277
d = c;
278
c = b;
279
b += rol32(a + f + K[i + 2] + m[(7*i + 14) % 16], 15);
280
a = tmp;
281
282
f = c ^ (b | ~d);
283
tmp = d;
284
d = c;
285
c = b;
286
b += rol32(a + f + K[i + 3] + m[(7*i + 5) % 16], 21);
287
a = tmp;
288
}
289
290
a0 += a;
291
b0 += b;
292
c0 += c;
293
d0 += d;
294
295
p += MD5_BLOCK_LENGTH;
296
len -= MD5_BLOCK_LENGTH;
297
}
298
299
ctx->state[0] = a0;
300
ctx->state[1] = b0;
301
ctx->state[2] = c0;
302
ctx->state[3] = d0;
303
}
304
#endif /* !defined(MD5_ASM) */
305
306
#ifdef WEAK_REFS
307
/* When building libmd, provide weak references. Note: this is not
308
activated in the context of compiling these sources for internal
309
use in libcrypt.
310
*/
311
#undef MD5Init
312
__weak_reference(_libmd_MD5Init, MD5Init);
313
#undef MD5Update
314
__weak_reference(_libmd_MD5Update, MD5Update);
315
#undef MD5Final
316
__weak_reference(_libmd_MD5Final, MD5Final);
317
#endif
318
319