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 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