1 /* 2 * InspIRCd -- Internet Relay Chat Daemon 3 * 4 * Copyright (C) 2014 Daniel Vassdal <shutter@canternet.org> 5 * Copyright (C) 2013, 2015, 2017 Sadie Powell <sadie@witchery.services> 6 * Copyright (C) 2012 Robby <robby@chatbelgie.be> 7 * Copyright (C) 2012 Garrett Holmstrom <gholms@fedoraproject.org> 8 * Copyright (C) 2009 Uli Schlachter <psychon@inspircd.org> 9 * Copyright (C) 2009 Daniel De Graaf <danieldg@inspircd.org> 10 * Copyright (C) 2007 Dennis Friis <peavey@inspircd.org> 11 * Copyright (C) 2006, 2010 Craig Edwards <brain@inspircd.org> 12 * 13 * This file is part of InspIRCd. InspIRCd is free software: you can 14 * redistribute it and/or modify it under the terms of the GNU General Public 15 * License as published by the Free Software Foundation, version 2. 16 * 17 * This program is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 19 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 20 * details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program. If not, see <http://www.gnu.org/licenses/>. 24 */ 25 26 27 #include "inspircd.h" 28 #include "modules/hash.h" 29 30 /* The four core functions - F1 is optimized somewhat */ 31 #define F1(x, y, z) (z ^ (x & (y ^ z))) 32 #define F2(x, y, z) F1(z, x, y) 33 #define F3(x, y, z) (x ^ y ^ z) 34 #define F4(x, y, z) (y ^ (x | ~z)) 35 36 /* This is the central step in the MD5 algorithm. */ 37 #define MD5STEP(f,w,x,y,z,in,s) \ 38 (w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x) 39 40 typedef uint32_t word32; /* NOT unsigned long. We don't support 16 bit platforms, anyway. */ 41 typedef unsigned char byte; 42 43 /** An MD5 context, used by m_opermd5 44 */ 45 class MD5Context 46 { 47 public: 48 word32 buf[4]; 49 word32 bytes[2]; 50 word32 in[16]; 51 }; 52 53 class MD5Provider : public HashProvider 54 { byteSwap(word32 * buf,unsigned words)55 void byteSwap(word32 *buf, unsigned words) 56 { 57 byte *p = (byte *)buf; 58 59 do 60 { 61 *buf++ = (word32)((unsigned)p[3] << 8 | p[2]) << 16 | 62 ((unsigned)p[1] << 8 | p[0]); 63 p += 4; 64 } while (--words); 65 } 66 MD5Init(MD5Context * ctx)67 void MD5Init(MD5Context *ctx) 68 { 69 /* These are the defaults for md5 */ 70 ctx->buf[0] = 0x67452301; 71 ctx->buf[1] = 0xefcdab89; 72 ctx->buf[2] = 0x98badcfe; 73 ctx->buf[3] = 0x10325476; 74 75 ctx->bytes[0] = 0; 76 ctx->bytes[1] = 0; 77 } 78 MD5Update(MD5Context * ctx,byte const * buf,int len)79 void MD5Update(MD5Context *ctx, byte const *buf, int len) 80 { 81 word32 t; 82 83 /* Update byte count */ 84 85 t = ctx->bytes[0]; 86 if ((ctx->bytes[0] = t + len) < t) 87 ctx->bytes[1]++; /* Carry from low to high */ 88 89 t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */ 90 if ((unsigned)t > (unsigned)len) 91 { 92 memcpy((byte *)ctx->in + 64 - (unsigned)t, buf, len); 93 return; 94 } 95 /* First chunk is an odd size */ 96 memcpy((byte *)ctx->in + 64 - (unsigned)t, buf, (unsigned)t); 97 byteSwap(ctx->in, 16); 98 MD5Transform(ctx->buf, ctx->in); 99 buf += (unsigned)t; 100 len -= (unsigned)t; 101 102 /* Process data in 64-byte chunks */ 103 while (len >= 64) 104 { 105 memcpy(ctx->in, buf, 64); 106 byteSwap(ctx->in, 16); 107 MD5Transform(ctx->buf, ctx->in); 108 buf += 64; 109 len -= 64; 110 } 111 112 /* Handle any remaining bytes of data. */ 113 memcpy(ctx->in, buf, len); 114 } 115 MD5Final(byte digest[16],MD5Context * ctx)116 void MD5Final(byte digest[16], MD5Context *ctx) 117 { 118 int count = (int)(ctx->bytes[0] & 0x3f); /* Bytes in ctx->in */ 119 byte *p = (byte *)ctx->in + count; /* First unused byte */ 120 121 /* Set the first char of padding to 0x80. There is always room. */ 122 *p++ = 0x80; 123 124 /* Bytes of padding needed to make 56 bytes (-8..55) */ 125 count = 56 - 1 - count; 126 127 if (count < 0) 128 { /* Padding forces an extra block */ 129 memset(p, 0, count+8); 130 byteSwap(ctx->in, 16); 131 MD5Transform(ctx->buf, ctx->in); 132 p = (byte *)ctx->in; 133 count = 56; 134 } 135 memset(p, 0, count+8); 136 byteSwap(ctx->in, 14); 137 138 /* Append length in bits and transform */ 139 ctx->in[14] = ctx->bytes[0] << 3; 140 ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29; 141 MD5Transform(ctx->buf, ctx->in); 142 143 byteSwap(ctx->buf, 4); 144 memcpy(digest, ctx->buf, 16); 145 memset(ctx, 0, sizeof(*ctx)); 146 } 147 MD5Transform(word32 buf[4],word32 const in[16])148 void MD5Transform(word32 buf[4], word32 const in[16]) 149 { 150 word32 a, b, c, d; 151 152 a = buf[0]; 153 b = buf[1]; 154 c = buf[2]; 155 d = buf[3]; 156 157 MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); 158 MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); 159 MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); 160 MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); 161 MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); 162 MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); 163 MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); 164 MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); 165 MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); 166 MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); 167 MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); 168 MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); 169 MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); 170 MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); 171 MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); 172 MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); 173 174 MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); 175 MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); 176 MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); 177 MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); 178 MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); 179 MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); 180 MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); 181 MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); 182 MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); 183 MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); 184 MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); 185 MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); 186 MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); 187 MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); 188 MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); 189 MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); 190 191 MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); 192 MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); 193 MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); 194 MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); 195 MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); 196 MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); 197 MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); 198 MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); 199 MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); 200 MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); 201 MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); 202 MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); 203 MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); 204 MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); 205 MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); 206 MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); 207 208 MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); 209 MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); 210 MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); 211 MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); 212 MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); 213 MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); 214 MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); 215 MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); 216 MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); 217 MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); 218 MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); 219 MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); 220 MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); 221 MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); 222 MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); 223 MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); 224 225 buf[0] += a; 226 buf[1] += b; 227 buf[2] += c; 228 buf[3] += d; 229 } 230 231 MyMD5(void * dest,void * orig,int len)232 void MyMD5(void *dest, void *orig, int len) 233 { 234 MD5Context context; 235 MD5Init(&context); 236 MD5Update(&context, (const unsigned char*)orig, len); 237 MD5Final((unsigned char*)dest, &context); 238 } 239 240 public: GenerateRaw(const std::string & data)241 std::string GenerateRaw(const std::string& data) CXX11_OVERRIDE 242 { 243 char res[16]; 244 MyMD5(res, (void*)data.data(), data.length()); 245 return std::string(res, 16); 246 } 247 MD5Provider(Module * parent)248 MD5Provider(Module* parent) : HashProvider(parent, "md5", 16, 64) {} 249 }; 250 251 class ModuleMD5 : public Module 252 { 253 MD5Provider md5; 254 public: ModuleMD5()255 ModuleMD5() : md5(this) 256 { 257 } 258 GetVersion()259 Version GetVersion() CXX11_OVERRIDE 260 { 261 return Version("Allows other modules to generate MD5 hashes.",VF_VENDOR); 262 } 263 }; 264 265 MODULE_INIT(ModuleMD5) 266