anope- supernets anope source code & configuration |
git clone git://git.acid.vegas/anope.git |
Log | Files | Refs | Archive | README |
enc_md5.cpp (12093B)
1 /* Module for encryption using MD5. 2 * 3 * Modified for Anope. 4 * (C) 2003-2022 Anope Team 5 * Contact us at team@anope.org 6 * 7 * Taken from IRC Services and is copyright (c) 1996-2002 Andrew Church. 8 * E-mail: <achurch@achurch.org> 9 * Parts written by Andrew Kempe and others. 10 * This program is free but copyrighted software; see the file COPYING for 11 * details. 12 */ 13 14 #include "module.h" 15 #include "modules/encryption.h" 16 17 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 18 rights reserved. 19 20 License to copy and use this software is granted provided that it 21 is identified as the "RSA Data Security, Inc. MD5 Message-Digest 22 Algorithm" in all material mentioning or referencing this software 23 or this function. 24 25 License is also granted to make and use derivative works provided 26 that such works are identified as "derived from the RSA Data 27 Security, Inc. MD5 Message-Digest Algorithm" in all material 28 mentioning or referencing the derived work. 29 30 RSA Data Security, Inc. makes no representations concerning either 31 the merchantability of this software or the suitability of this 32 software for any particular purpose. It is provided "as is" 33 without express or implied warranty of any kind. 34 35 These notices must be retained in any copies of any part of this 36 documentation and/or software. 37 */ 38 39 static unsigned char PADDING[64] = { 40 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 41 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 43 }; 44 45 /* F, G, H and I are basic MD5 functions. 46 */ 47 inline static unsigned F(unsigned x, unsigned y, unsigned z) { return (x & y) | (~x & z); } 48 inline static unsigned G(unsigned x, unsigned y, unsigned z) { return (x & z) | (y & ~z); } 49 inline static unsigned H(unsigned x, unsigned y, unsigned z) { return x ^ y ^ z; } 50 inline static unsigned I(unsigned x, unsigned y, unsigned z) { return y ^ (x | ~z); } 51 52 /* ROTATE_LEFT rotates x left n bits. 53 */ 54 inline static unsigned ROTATE_LEFT(unsigned x, unsigned n) { return (x << n) | (x >> (32 - n)); } 55 56 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 57 * Rotation is separate from addition to prevent recomputation. 58 */ 59 inline static void FF(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac) 60 { 61 a += F(b, c, d) + x + ac; 62 a = ROTATE_LEFT(a, s); 63 a += b; 64 } 65 inline static void GG(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac) 66 { 67 a += G(b, c, d) + x + ac; 68 a = ROTATE_LEFT(a, s); 69 a += b; 70 } 71 inline static void HH(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac) 72 { 73 a += H(b, c, d) + x + ac; 74 a = ROTATE_LEFT(a, s); 75 a += b; 76 } 77 inline static void II(unsigned &a, unsigned b, unsigned c, unsigned d, unsigned x, unsigned s, unsigned ac) 78 { 79 a += I(b, c, d) + x + ac; 80 a = ROTATE_LEFT(a, s); 81 a += b; 82 } 83 84 static const uint32_t md5_iv[4] = 85 { 86 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476 87 }; 88 89 class MD5Context : public Encryption::Context 90 { 91 unsigned state[4]; /* state (ABCD) */ 92 unsigned count[2]; /* number of bits, modulo 2^64 (lsb first) */ 93 unsigned char buffer[64]; /* input buffer */ 94 unsigned char digest[16]; /* final digest */ 95 96 /* Constants for MD5Transform routine. 97 */ 98 enum 99 { 100 S11 = 7, 101 S12 = 12, 102 S13 = 17, 103 S14 = 22, 104 S21 = 5, 105 S22 = 9, 106 S23 = 14, 107 S24 = 20, 108 S31 = 4, 109 S32 = 11, 110 S33 = 16, 111 S34 = 23, 112 S41 = 6, 113 S42 = 10, 114 S43 = 15, 115 S44 = 21 116 }; 117 118 /* MD5 basic transformation. Transforms state based on block. 119 */ 120 void Transform(const unsigned char block[64]) 121 { 122 unsigned a = state[0], b = state[1], c = state[2], d = state[3], x[16]; 123 124 Decode(x, block, 64); 125 126 /* Round 1 */ 127 FF(a, b, c, d, x[0], S11, 0xd76aa478); /* 1 */ 128 FF(d, a, b, c, x[1], S12, 0xe8c7b756); /* 2 */ 129 FF(c, d, a, b, x[2], S13, 0x242070db); /* 3 */ 130 FF(b, c, d, a, x[3], S14, 0xc1bdceee); /* 4 */ 131 FF(a, b, c, d, x[4], S11, 0xf57c0faf); /* 5 */ 132 FF(d, a, b, c, x[5], S12, 0x4787c62a); /* 6 */ 133 FF(c, d, a, b, x[6], S13, 0xa8304613); /* 7 */ 134 FF(b, c, d, a, x[7], S14, 0xfd469501); /* 8 */ 135 FF(a, b, c, d, x[8], S11, 0x698098d8); /* 9 */ 136 FF(d, a, b, c, x[9], S12, 0x8b44f7af); /* 10 */ 137 FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ 138 FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ 139 FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ 140 FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ 141 FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ 142 FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ 143 144 /* Round 2 */ 145 GG(a, b, c, d, x[1], S21, 0xf61e2562); /* 17 */ 146 GG(d, a, b, c, x[6], S22, 0xc040b340); /* 18 */ 147 GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ 148 GG(b, c, d, a, x[0], S24, 0xe9b6c7aa); /* 20 */ 149 GG(a, b, c, d, x[5], S21, 0xd62f105d); /* 21 */ 150 GG(d, a, b, c, x[10], S22, 0x2441453); /* 22 */ 151 GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ 152 GG(b, c, d, a, x[4], S24, 0xe7d3fbc8); /* 24 */ 153 GG(a, b, c, d, x[9], S21, 0x21e1cde6); /* 25 */ 154 GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ 155 GG(c, d, a, b, x[3], S23, 0xf4d50d87); /* 27 */ 156 GG(b, c, d, a, x[8], S24, 0x455a14ed); /* 28 */ 157 GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ 158 GG(d, a, b, c, x[2], S22, 0xfcefa3f8); /* 30 */ 159 GG(c, d, a, b, x[7], S23, 0x676f02d9); /* 31 */ 160 GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ 161 162 /* Round 3 */ 163 HH(a, b, c, d, x[5], S31, 0xfffa3942); /* 33 */ 164 HH(d, a, b, c, x[8], S32, 0x8771f681); /* 34 */ 165 HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ 166 HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ 167 HH(a, b, c, d, x[1], S31, 0xa4beea44); /* 37 */ 168 HH(d, a, b, c, x[4], S32, 0x4bdecfa9); /* 38 */ 169 HH(c, d, a, b, x[7], S33, 0xf6bb4b60); /* 39 */ 170 HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ 171 HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ 172 HH(d, a, b, c, x[0], S32, 0xeaa127fa); /* 42 */ 173 HH(c, d, a, b, x[3], S33, 0xd4ef3085); /* 43 */ 174 HH(b, c, d, a, x[6], S34, 0x4881d05); /* 44 */ 175 HH(a, b, c, d, x[9], S31, 0xd9d4d039); /* 45 */ 176 HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ 177 HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ 178 HH(b, c, d, a, x[2], S34, 0xc4ac5665); /* 48 */ 179 180 /* Round 4 */ 181 II(a, b, c, d, x[0], S41, 0xf4292244); /* 49 */ 182 II(d, a, b, c, x[7], S42, 0x432aff97); /* 50 */ 183 II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ 184 II(b, c, d, a, x[5], S44, 0xfc93a039); /* 52 */ 185 II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ 186 II(d, a, b, c, x[3], S42, 0x8f0ccc92); /* 54 */ 187 II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ 188 II(b, c, d, a, x[1], S44, 0x85845dd1); /* 56 */ 189 II(a, b, c, d, x[8], S41, 0x6fa87e4f); /* 57 */ 190 II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ 191 II(c, d, a, b, x[6], S43, 0xa3014314); /* 59 */ 192 II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ 193 II(a, b, c, d, x[4], S41, 0xf7537e82); /* 61 */ 194 II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ 195 II(c, d, a, b, x[2], S43, 0x2ad7d2bb); /* 63 */ 196 II(b, c, d, a, x[9], S44, 0xeb86d391); /* 64 */ 197 198 state[0] += a; 199 state[1] += b; 200 state[2] += c; 201 state[3] += d; 202 203 /* Zeroize sensitive information. */ 204 memset(x, 0, sizeof(x)); 205 } 206 207 /* Encodes input (unsigned) into output (unsigned char). Assumes len is 208 * a multiple of 4. 209 */ 210 void Encode(unsigned char *output, unsigned *input, unsigned len) 211 { 212 for (unsigned i = 0, j = 0; j < len; ++i, j += 4) 213 { 214 output[j] = static_cast<unsigned char>(input[i] & 0xff); 215 output[j + 1] = static_cast<unsigned char>((input[i] >> 8) & 0xff); 216 output[j + 2] = static_cast<unsigned char>((input[i] >> 16) & 0xff); 217 output[j + 3] = static_cast<unsigned char>((input[i] >> 24) & 0xff); 218 } 219 } 220 221 /* Decodes input (unsigned char) into output (unsigned). Assumes len is 222 * a multiple of 4. 223 */ 224 void Decode(unsigned *output, const unsigned char *input, unsigned len) 225 { 226 for (unsigned i = 0, j = 0; j < len; ++i, j += 4) 227 output[i] = static_cast<unsigned>(input[j]) | (static_cast<unsigned>(input[j + 1]) << 8) | (static_cast<unsigned>(input[j + 2]) << 16) | (static_cast<unsigned>(input[j + 3]) << 24); 228 } 229 230 public: 231 MD5Context(Encryption::IV *iv = NULL) 232 { 233 if (iv != NULL) 234 { 235 if (iv->second != 4) 236 throw CoreException("Invalid IV size"); 237 /* Load magic initialization constants. */ 238 for (int i = 0; i < 4; ++i) 239 this->state[i] = iv->first[i]; 240 } 241 else 242 for (int i = 0; i < 4; ++i) 243 this->state[i] = md5_iv[i]; 244 245 this->count[0] = this->count[1] = 0; 246 memset(this->buffer, 0, sizeof(this->buffer)); 247 } 248 249 /* MD5 block update operation. Continues an MD5 message-digest 250 * operation, processing another message block, and updating the 251 * context. 252 */ 253 void Update(const unsigned char *input, size_t len) anope_override 254 { 255 unsigned i, index, partLen; 256 257 /* Compute number of bytes mod 64 */ 258 index = (this->count[0] >> 3) & 0x3F; 259 260 /* Update number of bits */ 261 if ((this->count[0] += len << 3) < (len << 3)) 262 ++this->count[1]; 263 this->count[1] += len >> 29; 264 265 partLen = 64 - index; 266 267 /* Transform as many times as possible. */ 268 if (len >= partLen) 269 { 270 memcpy(&this->buffer[index], input, partLen); 271 this->Transform(this->buffer); 272 273 for (i = partLen; i + 63 < len; i += 64) 274 this->Transform(&input[i]); 275 276 index = 0; 277 } 278 else 279 i = 0; 280 281 /* Buffer remaining input */ 282 memcpy(&this->buffer[index], &input[i], len - i); 283 } 284 285 /* MD5 finalization. Ends an MD5 message-digest opera 286 * the message digest and zeroizing the context. 287 */ 288 void Finalize() anope_override 289 { 290 unsigned char bits[8]; 291 unsigned index, padLen; 292 293 /* Save number of bits */ 294 this->Encode(bits, this->count, 8); 295 296 /* Pad out to 56 mod 64. */ 297 index = (this->count[0] >> 3) & 0x3f; 298 padLen = index < 56 ? 56 - index : 120 - index; 299 this->Update(PADDING, padLen); 300 301 /* Append length (before padding) */ 302 this->Update(bits, 8); 303 /* Store state in digest */ 304 this->Encode(digest, this->state, 16); 305 306 /* Zeroize sensitive information. */ 307 memset(this->state, 0, sizeof(this->state)); 308 memset(this->count, 0, sizeof(this->count)); 309 memset(this->buffer, 0, sizeof(this->buffer)); 310 } 311 312 Encryption::Hash GetFinalizedHash() anope_override 313 { 314 Encryption::Hash hash; 315 hash.first = this->digest; 316 hash.second = sizeof(this->digest); 317 return hash; 318 } 319 }; 320 321 class MD5Provider : public Encryption::Provider 322 { 323 public: 324 MD5Provider(Module *creator) : Encryption::Provider(creator, "md5") { } 325 326 Encryption::Context *CreateContext(Encryption::IV *iv) anope_override 327 { 328 return new MD5Context(iv); 329 } 330 331 Encryption::IV GetDefaultIV() anope_override 332 { 333 Encryption::IV iv; 334 iv.first = md5_iv; 335 iv.second = sizeof(md5_iv) / sizeof(uint32_t); 336 return iv; 337 } 338 }; 339 340 class EMD5 : public Module 341 { 342 MD5Provider md5provider; 343 344 public: 345 EMD5(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, ENCRYPTION | VENDOR), 346 md5provider(this) 347 { 348 349 } 350 351 EventReturn OnEncrypt(const Anope::string &src, Anope::string &dest) anope_override 352 { 353 MD5Context context; 354 355 context.Update(reinterpret_cast<const unsigned char *>(src.c_str()), src.length()); 356 context.Finalize(); 357 358 Encryption::Hash hash = context.GetFinalizedHash(); 359 360 Anope::string buf = "md5:" + Anope::Hex(reinterpret_cast<const char *>(hash.first), hash.second); 361 362 Log(LOG_DEBUG_2) << "(enc_md5) hashed password from [" << src << "] to [" << buf << "]"; 363 dest = buf; 364 return EVENT_ALLOW; 365 } 366 367 void OnCheckAuthentication(User *, IdentifyRequest *req) anope_override 368 { 369 const NickAlias *na = NickAlias::Find(req->GetAccount()); 370 if (na == NULL) 371 return; 372 NickCore *nc = na->nc; 373 374 size_t pos = nc->pass.find(':'); 375 if (pos == Anope::string::npos) 376 return; 377 Anope::string hash_method(nc->pass.begin(), nc->pass.begin() + pos); 378 if (!hash_method.equals_cs("md5")) 379 return; 380 381 Anope::string buf; 382 this->OnEncrypt(req->GetPassword(), buf); 383 if (nc->pass.equals_cs(buf)) 384 { 385 /* if we are NOT the first module in the list, 386 * we want to re-encrypt the pass with the new encryption 387 */ 388 if (ModuleManager::FindFirstOf(ENCRYPTION) != this) 389 Anope::Encrypt(req->GetPassword(), nc->pass); 390 req->Success(this); 391 } 392 } 393 }; 394 395 MODULE_INIT(EMD5)