1 /*-
2 * Copyright (c) 2024, 2025 Robert Clausecker <fuz@FreeBSD.org>
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
MD5Init(MD5_CTX * ctx)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
MD5Update(MD5_CTX * ctx,const void * data,unsigned int len)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
MD5Pad(MD5_CTX * ctx)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
MD5Final(unsigned char md[16],MD5_CTX * ctx)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
rol32(uint32_t a,int b)142 rol32(uint32_t a, int b)
143 {
144 return (a << b | a >> (32 - b));
145 }
146
147 static void
md5block(MD5_CTX * ctx,const void * data,size_t len)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