1 /* 2 ********************************************************************** 3 ** md5.c ** 4 ** RSA Data Security, Inc. MD5 Message Digest Algorithm ** 5 ** Created: 2/17/90 RLR ** 6 ** Revised: 1/91 SRD,AJ,BSK,JT Reference C Version ** 7 ********************************************************************** 8 */ 9 10 module dmd.backend.md5; 11 12 /* 13 ********************************************************************** 14 ** Copyright (C) 1990, RSA Data Security, Inc. All rights reserved. ** 15 ** ** 16 ** License to copy and use this software is granted provided that ** 17 ** it is identified as the "RSA Data Security, Inc. MD5 Message ** 18 ** Digest Algorithm" in all material mentioning or referencing this ** 19 ** software or this function. ** 20 ** ** 21 ** License is also granted to make and use derivative works ** 22 ** provided that such works are identified as "derived from the RSA ** 23 ** Data Security, Inc. MD5 Message Digest Algorithm" in all ** 24 ** material mentioning or referencing the derived work. ** 25 ** ** 26 ** RSA Data Security, Inc. makes no representations concerning ** 27 ** either the merchantability of this software or the suitability ** 28 ** of this software for any particular purpose. It is provided "as ** 29 ** is" without express or implied warranty of any kind. ** 30 ** ** 31 ** These notices must be retained in any copies of any part of this ** 32 ** documentation and/or software. ** 33 ********************************************************************** 34 */ 35 36 /* -- include the following line if the md5.h header file is separate -- */ 37 38 extern (C++): 39 nothrow: 40 @nogc: 41 private: 42 43 /* typedef a 32 bit type */ 44 alias UINT4 = uint; 45 46 /* Data structure for MD5 (Message Digest) computation */ 47 public struct MD5_CTX { 48 UINT4[2] i; /* number of _bits_ handled mod 2^64 */ 49 UINT4[4] buf; /* scratch buffer */ 50 ubyte[64] in_; /* input buffer */ 51 ubyte[16] digest; /* actual digest after MD5Final call */ 52 } 53 54 55 __gshared ubyte[64] PADDING = [ 56 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 64 ]; 65 66 /* F, G and H are basic MD5 functions: selection, majority, parity */ 67 UINT4 F(UINT4 x, UINT4 y, UINT4 z) { return (x & y) | (~x & z); } 68 UINT4 G(UINT4 x, UINT4 y, UINT4 z) { return (x & z) | (y & ~z); } 69 UINT4 H(UINT4 x, UINT4 y, UINT4 z) { return x ^ y ^ z; } 70 UINT4 I(UINT4 x, UINT4 y, UINT4 z) { return y ^ (x | ~z); } 71 72 /* ROTATE_LEFT rotates x left n bits */ 73 UINT4 ROTATE_LEFT(UINT4 x, UINT4 n) { return (x << n) | (x >> (32-n)); } 74 75 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4 */ 76 /* Rotation is separate from addition to prevent recomputation */ 77 void FF(ref UINT4 a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac) 78 {a += F (b, c, d) + x + cast(UINT4)ac; 79 a = ROTATE_LEFT (a, s); 80 a += b; 81 } 82 void GG(ref UINT4 a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac) 83 {a += G (b, c, d) + x + cast(UINT4)ac; 84 a = ROTATE_LEFT (a, s); 85 a += b; 86 } 87 void HH(ref UINT4 a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac) 88 {a += H (b, c, d) + x + cast(UINT4)ac; 89 a = ROTATE_LEFT (a, s); 90 a += b; 91 } 92 void II(ref UINT4 a, UINT4 b, UINT4 c, UINT4 d, UINT4 x, UINT4 s, UINT4 ac) 93 {a += I (b, c, d) + x + cast(UINT4)ac; 94 a = ROTATE_LEFT (a, s); 95 a += b; 96 } 97 98 public void MD5Init (MD5_CTX *mdContext) 99 { 100 mdContext.i[0] = mdContext.i[1] = cast(UINT4)0; 101 102 /* Load magic initialization constants. 103 */ 104 mdContext.buf[0] = cast(UINT4)0x67452301; 105 mdContext.buf[1] = cast(UINT4)0xefcdab89; 106 mdContext.buf[2] = cast(UINT4)0x98badcfe; 107 mdContext.buf[3] = cast(UINT4)0x10325476; 108 } 109 110 public void MD5Update (MD5_CTX *mdContext, ubyte *inBuf, uint inLen) 111 { 112 UINT4[16] in_; 113 int mdi; 114 uint i, ii; 115 116 /* compute number of bytes mod 64 */ 117 mdi = cast(int)((mdContext.i[0] >> 3) & 0x3F); 118 119 /* update number of bits */ 120 if ((mdContext.i[0] + (cast(UINT4)inLen << 3)) < mdContext.i[0]) 121 mdContext.i[1]++; 122 mdContext.i[0] += (cast(UINT4)inLen << 3); 123 mdContext.i[1] += (cast(UINT4)inLen >> 29); 124 125 while (inLen--) { 126 /* add new character to buffer, increment mdi */ 127 mdContext.in_[mdi++] = *inBuf++; 128 129 /* transform if necessary */ 130 if (mdi == 0x40) { 131 for (i = 0, ii = 0; i < 16; i++, ii += 4) 132 in_[i] = ((cast(UINT4)mdContext.in_[ii+3]) << 24) | 133 ((cast(UINT4)mdContext.in_[ii+2]) << 16) | 134 ((cast(UINT4)mdContext.in_[ii+1]) << 8) | 135 (cast(UINT4)mdContext.in_[ii]); 136 Transform (&mdContext.buf[0], &in_[0]); 137 mdi = 0; 138 } 139 } 140 } 141 142 public void MD5Final (MD5_CTX *mdContext) 143 { 144 UINT4[16] in_; 145 int mdi; 146 uint i, ii; 147 uint padLen; 148 149 /* save number of bits */ 150 in_[14] = mdContext.i[0]; 151 in_[15] = mdContext.i[1]; 152 153 /* compute number of bytes mod 64 */ 154 mdi = cast(int)((mdContext.i[0] >> 3) & 0x3F); 155 156 /* pad out to 56 mod 64 */ 157 padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); 158 MD5Update (mdContext, &PADDING[0], padLen); 159 160 /* append length in bits and transform */ 161 for (i = 0, ii = 0; i < 14; i++, ii += 4) 162 in_[i] = ((cast(UINT4)mdContext.in_[ii+3]) << 24) | 163 ((cast(UINT4)mdContext.in_[ii+2]) << 16) | 164 ((cast(UINT4)mdContext.in_[ii+1]) << 8) | 165 (cast(UINT4)mdContext.in_[ii]); 166 Transform (&mdContext.buf[0], &in_[0]); 167 168 /* store buffer in digest */ 169 for (i = 0, ii = 0; i < 4; i++, ii += 4) { 170 mdContext.digest[ii] = cast(ubyte)(mdContext.buf[i] & 0xFF); 171 mdContext.digest[ii+1] = 172 cast(ubyte)((mdContext.buf[i] >> 8) & 0xFF); 173 mdContext.digest[ii+2] = 174 cast(ubyte)((mdContext.buf[i] >> 16) & 0xFF); 175 mdContext.digest[ii+3] = 176 cast(ubyte)((mdContext.buf[i] >> 24) & 0xFF); 177 } 178 } 179 180 /* Basic MD5 step. Transform buf based on in. 181 */ 182 void Transform (UINT4 *buf, UINT4 *in_) 183 { 184 UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; 185 186 /* Round 1 */ 187 enum S11 = 7; 188 enum S12 = 12; 189 enum S13 = 17; 190 enum S14 = 22; 191 FF ( a, b, c, d, in_[ 0], S11, 3614090360U); /* 1 */ 192 FF ( d, a, b, c, in_[ 1], S12, 3905402710U); /* 2 */ 193 FF ( c, d, a, b, in_[ 2], S13, 606105819U); /* 3 */ 194 FF ( b, c, d, a, in_[ 3], S14, 3250441966U); /* 4 */ 195 FF ( a, b, c, d, in_[ 4], S11, 4118548399U); /* 5 */ 196 FF ( d, a, b, c, in_[ 5], S12, 1200080426U); /* 6 */ 197 FF ( c, d, a, b, in_[ 6], S13, 2821735955U); /* 7 */ 198 FF ( b, c, d, a, in_[ 7], S14, 4249261313U); /* 8 */ 199 FF ( a, b, c, d, in_[ 8], S11, 1770035416U); /* 9 */ 200 FF ( d, a, b, c, in_[ 9], S12, 2336552879U); /* 10 */ 201 FF ( c, d, a, b, in_[10], S13, 4294925233U); /* 11 */ 202 FF ( b, c, d, a, in_[11], S14, 2304563134U); /* 12 */ 203 FF ( a, b, c, d, in_[12], S11, 1804603682U); /* 13 */ 204 FF ( d, a, b, c, in_[13], S12, 4254626195U); /* 14 */ 205 FF ( c, d, a, b, in_[14], S13, 2792965006U); /* 15 */ 206 FF ( b, c, d, a, in_[15], S14, 1236535329U); /* 16 */ 207 208 /* Round 2 */ 209 enum S21 = 5; 210 enum S22 = 9; 211 enum S23 = 14; 212 enum S24 = 20; 213 GG ( a, b, c, d, in_[ 1], S21, 4129170786U); /* 17 */ 214 GG ( d, a, b, c, in_[ 6], S22, 3225465664U); /* 18 */ 215 GG ( c, d, a, b, in_[11], S23, 643717713U); /* 19 */ 216 GG ( b, c, d, a, in_[ 0], S24, 3921069994U); /* 20 */ 217 GG ( a, b, c, d, in_[ 5], S21, 3593408605U); /* 21 */ 218 GG ( d, a, b, c, in_[10], S22, 38016083U); /* 22 */ 219 GG ( c, d, a, b, in_[15], S23, 3634488961U); /* 23 */ 220 GG ( b, c, d, a, in_[ 4], S24, 3889429448U); /* 24 */ 221 GG ( a, b, c, d, in_[ 9], S21, 568446438U); /* 25 */ 222 GG ( d, a, b, c, in_[14], S22, 3275163606U); /* 26 */ 223 GG ( c, d, a, b, in_[ 3], S23, 4107603335U); /* 27 */ 224 GG ( b, c, d, a, in_[ 8], S24, 1163531501U); /* 28 */ 225 GG ( a, b, c, d, in_[13], S21, 2850285829U); /* 29 */ 226 GG ( d, a, b, c, in_[ 2], S22, 4243563512U); /* 30 */ 227 GG ( c, d, a, b, in_[ 7], S23, 1735328473U); /* 31 */ 228 GG ( b, c, d, a, in_[12], S24, 2368359562U); /* 32 */ 229 230 /* Round 3 */ 231 enum S31 = 4; 232 enum S32 = 11; 233 enum S33 = 16; 234 enum S34 = 23; 235 HH ( a, b, c, d, in_[ 5], S31, 4294588738U); /* 33 */ 236 HH ( d, a, b, c, in_[ 8], S32, 2272392833U); /* 34 */ 237 HH ( c, d, a, b, in_[11], S33, 1839030562U); /* 35 */ 238 HH ( b, c, d, a, in_[14], S34, 4259657740U); /* 36 */ 239 HH ( a, b, c, d, in_[ 1], S31, 2763975236U); /* 37 */ 240 HH ( d, a, b, c, in_[ 4], S32, 1272893353U); /* 38 */ 241 HH ( c, d, a, b, in_[ 7], S33, 4139469664U); /* 39 */ 242 HH ( b, c, d, a, in_[10], S34, 3200236656U); /* 40 */ 243 HH ( a, b, c, d, in_[13], S31, 681279174U); /* 41 */ 244 HH ( d, a, b, c, in_[ 0], S32, 3936430074U); /* 42 */ 245 HH ( c, d, a, b, in_[ 3], S33, 3572445317U); /* 43 */ 246 HH ( b, c, d, a, in_[ 6], S34, 76029189U); /* 44 */ 247 HH ( a, b, c, d, in_[ 9], S31, 3654602809U); /* 45 */ 248 HH ( d, a, b, c, in_[12], S32, 3873151461U); /* 46 */ 249 HH ( c, d, a, b, in_[15], S33, 530742520U); /* 47 */ 250 HH ( b, c, d, a, in_[ 2], S34, 3299628645U); /* 48 */ 251 252 /* Round 4 */ 253 enum S41 = 6; 254 enum S42 = 10; 255 enum S43 = 15; 256 enum S44 = 21; 257 II ( a, b, c, d, in_[ 0], S41, 4096336452U); /* 49 */ 258 II ( d, a, b, c, in_[ 7], S42, 1126891415U); /* 50 */ 259 II ( c, d, a, b, in_[14], S43, 2878612391U); /* 51 */ 260 II ( b, c, d, a, in_[ 5], S44, 4237533241U); /* 52 */ 261 II ( a, b, c, d, in_[12], S41, 1700485571U); /* 53 */ 262 II ( d, a, b, c, in_[ 3], S42, 2399980690U); /* 54 */ 263 II ( c, d, a, b, in_[10], S43, 4293915773U); /* 55 */ 264 II ( b, c, d, a, in_[ 1], S44, 2240044497U); /* 56 */ 265 II ( a, b, c, d, in_[ 8], S41, 1873313359U); /* 57 */ 266 II ( d, a, b, c, in_[15], S42, 4264355552U); /* 58 */ 267 II ( c, d, a, b, in_[ 6], S43, 2734768916U); /* 59 */ 268 II ( b, c, d, a, in_[13], S44, 1309151649U); /* 60 */ 269 II ( a, b, c, d, in_[ 4], S41, 4149444226U); /* 61 */ 270 II ( d, a, b, c, in_[11], S42, 3174756917U); /* 62 */ 271 II ( c, d, a, b, in_[ 2], S43, 718787259U); /* 63 */ 272 II ( b, c, d, a, in_[ 9], S44, 3951481745U); /* 64 */ 273 274 buf[0] += a; 275 buf[1] += b; 276 buf[2] += c; 277 buf[3] += d; 278 } 279 280 /* 281 ********************************************************************** 282 ** End of md5.c ** 283 ******************************* (cut) ******************************** 284 */ 285