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)