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