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 nothrow: 39 @nogc: 40 @safe: 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 @trusted 111 public void MD5Update (MD5_CTX *mdContext, ubyte *inBuf, uint inLen) 112 { 113 UINT4[16] in_; 114 int mdi; 115 uint i, ii; 116 117 /* compute number of bytes mod 64 */ 118 mdi = cast(int)((mdContext.i[0] >> 3) & 0x3F); 119 120 /* update number of bits */ 121 if ((mdContext.i[0] + (cast(UINT4)inLen << 3)) < mdContext.i[0]) 122 mdContext.i[1]++; 123 mdContext.i[0] += (cast(UINT4)inLen << 3); 124 mdContext.i[1] += (cast(UINT4)inLen >> 29); 125 126 while (inLen--) { 127 /* add new character to buffer, increment mdi */ 128 mdContext.in_[mdi++] = *inBuf++; 129 130 /* transform if necessary */ 131 if (mdi == 0x40) { 132 for (i = 0, ii = 0; i < 16; i++, ii += 4) 133 in_[i] = ((cast(UINT4)mdContext.in_[ii+3]) << 24) | 134 ((cast(UINT4)mdContext.in_[ii+2]) << 16) | 135 ((cast(UINT4)mdContext.in_[ii+1]) << 8) | 136 (cast(UINT4)mdContext.in_[ii]); 137 Transform (&mdContext.buf[0], &in_[0]); 138 mdi = 0; 139 } 140 } 141 } 142 143 @trusted 144 public void MD5Final (MD5_CTX *mdContext) 145 { 146 UINT4[16] in_; 147 int mdi; 148 uint i, ii; 149 uint padLen; 150 151 /* save number of bits */ 152 in_[14] = mdContext.i[0]; 153 in_[15] = mdContext.i[1]; 154 155 /* compute number of bytes mod 64 */ 156 mdi = cast(int)((mdContext.i[0] >> 3) & 0x3F); 157 158 /* pad out to 56 mod 64 */ 159 padLen = (mdi < 56) ? (56 - mdi) : (120 - mdi); 160 MD5Update (mdContext, &PADDING[0], padLen); 161 162 /* append length in bits and transform */ 163 for (i = 0, ii = 0; i < 14; i++, ii += 4) 164 in_[i] = ((cast(UINT4)mdContext.in_[ii+3]) << 24) | 165 ((cast(UINT4)mdContext.in_[ii+2]) << 16) | 166 ((cast(UINT4)mdContext.in_[ii+1]) << 8) | 167 (cast(UINT4)mdContext.in_[ii]); 168 Transform (&mdContext.buf[0], &in_[0]); 169 170 /* store buffer in digest */ 171 for (i = 0, ii = 0; i < 4; i++, ii += 4) { 172 mdContext.digest[ii] = cast(ubyte)(mdContext.buf[i] & 0xFF); 173 mdContext.digest[ii+1] = 174 cast(ubyte)((mdContext.buf[i] >> 8) & 0xFF); 175 mdContext.digest[ii+2] = 176 cast(ubyte)((mdContext.buf[i] >> 16) & 0xFF); 177 mdContext.digest[ii+3] = 178 cast(ubyte)((mdContext.buf[i] >> 24) & 0xFF); 179 } 180 } 181 182 /* Basic MD5 step. Transform buf based on in. 183 */ 184 @trusted 185 void Transform (UINT4 *buf, UINT4 *in_) 186 { 187 UINT4 a = buf[0], b = buf[1], c = buf[2], d = buf[3]; 188 189 /* Round 1 */ 190 enum S11 = 7; 191 enum S12 = 12; 192 enum S13 = 17; 193 enum S14 = 22; 194 FF ( a, b, c, d, in_[ 0], S11, 3614090360U); /* 1 */ 195 FF ( d, a, b, c, in_[ 1], S12, 3905402710U); /* 2 */ 196 FF ( c, d, a, b, in_[ 2], S13, 606105819U); /* 3 */ 197 FF ( b, c, d, a, in_[ 3], S14, 3250441966U); /* 4 */ 198 FF ( a, b, c, d, in_[ 4], S11, 4118548399U); /* 5 */ 199 FF ( d, a, b, c, in_[ 5], S12, 1200080426U); /* 6 */ 200 FF ( c, d, a, b, in_[ 6], S13, 2821735955U); /* 7 */ 201 FF ( b, c, d, a, in_[ 7], S14, 4249261313U); /* 8 */ 202 FF ( a, b, c, d, in_[ 8], S11, 1770035416U); /* 9 */ 203 FF ( d, a, b, c, in_[ 9], S12, 2336552879U); /* 10 */ 204 FF ( c, d, a, b, in_[10], S13, 4294925233U); /* 11 */ 205 FF ( b, c, d, a, in_[11], S14, 2304563134U); /* 12 */ 206 FF ( a, b, c, d, in_[12], S11, 1804603682U); /* 13 */ 207 FF ( d, a, b, c, in_[13], S12, 4254626195U); /* 14 */ 208 FF ( c, d, a, b, in_[14], S13, 2792965006U); /* 15 */ 209 FF ( b, c, d, a, in_[15], S14, 1236535329U); /* 16 */ 210 211 /* Round 2 */ 212 enum S21 = 5; 213 enum S22 = 9; 214 enum S23 = 14; 215 enum S24 = 20; 216 GG ( a, b, c, d, in_[ 1], S21, 4129170786U); /* 17 */ 217 GG ( d, a, b, c, in_[ 6], S22, 3225465664U); /* 18 */ 218 GG ( c, d, a, b, in_[11], S23, 643717713U); /* 19 */ 219 GG ( b, c, d, a, in_[ 0], S24, 3921069994U); /* 20 */ 220 GG ( a, b, c, d, in_[ 5], S21, 3593408605U); /* 21 */ 221 GG ( d, a, b, c, in_[10], S22, 38016083U); /* 22 */ 222 GG ( c, d, a, b, in_[15], S23, 3634488961U); /* 23 */ 223 GG ( b, c, d, a, in_[ 4], S24, 3889429448U); /* 24 */ 224 GG ( a, b, c, d, in_[ 9], S21, 568446438U); /* 25 */ 225 GG ( d, a, b, c, in_[14], S22, 3275163606U); /* 26 */ 226 GG ( c, d, a, b, in_[ 3], S23, 4107603335U); /* 27 */ 227 GG ( b, c, d, a, in_[ 8], S24, 1163531501U); /* 28 */ 228 GG ( a, b, c, d, in_[13], S21, 2850285829U); /* 29 */ 229 GG ( d, a, b, c, in_[ 2], S22, 4243563512U); /* 30 */ 230 GG ( c, d, a, b, in_[ 7], S23, 1735328473U); /* 31 */ 231 GG ( b, c, d, a, in_[12], S24, 2368359562U); /* 32 */ 232 233 /* Round 3 */ 234 enum S31 = 4; 235 enum S32 = 11; 236 enum S33 = 16; 237 enum S34 = 23; 238 HH ( a, b, c, d, in_[ 5], S31, 4294588738U); /* 33 */ 239 HH ( d, a, b, c, in_[ 8], S32, 2272392833U); /* 34 */ 240 HH ( c, d, a, b, in_[11], S33, 1839030562U); /* 35 */ 241 HH ( b, c, d, a, in_[14], S34, 4259657740U); /* 36 */ 242 HH ( a, b, c, d, in_[ 1], S31, 2763975236U); /* 37 */ 243 HH ( d, a, b, c, in_[ 4], S32, 1272893353U); /* 38 */ 244 HH ( c, d, a, b, in_[ 7], S33, 4139469664U); /* 39 */ 245 HH ( b, c, d, a, in_[10], S34, 3200236656U); /* 40 */ 246 HH ( a, b, c, d, in_[13], S31, 681279174U); /* 41 */ 247 HH ( d, a, b, c, in_[ 0], S32, 3936430074U); /* 42 */ 248 HH ( c, d, a, b, in_[ 3], S33, 3572445317U); /* 43 */ 249 HH ( b, c, d, a, in_[ 6], S34, 76029189U); /* 44 */ 250 HH ( a, b, c, d, in_[ 9], S31, 3654602809U); /* 45 */ 251 HH ( d, a, b, c, in_[12], S32, 3873151461U); /* 46 */ 252 HH ( c, d, a, b, in_[15], S33, 530742520U); /* 47 */ 253 HH ( b, c, d, a, in_[ 2], S34, 3299628645U); /* 48 */ 254 255 /* Round 4 */ 256 enum S41 = 6; 257 enum S42 = 10; 258 enum S43 = 15; 259 enum S44 = 21; 260 II ( a, b, c, d, in_[ 0], S41, 4096336452U); /* 49 */ 261 II ( d, a, b, c, in_[ 7], S42, 1126891415U); /* 50 */ 262 II ( c, d, a, b, in_[14], S43, 2878612391U); /* 51 */ 263 II ( b, c, d, a, in_[ 5], S44, 4237533241U); /* 52 */ 264 II ( a, b, c, d, in_[12], S41, 1700485571U); /* 53 */ 265 II ( d, a, b, c, in_[ 3], S42, 2399980690U); /* 54 */ 266 II ( c, d, a, b, in_[10], S43, 4293915773U); /* 55 */ 267 II ( b, c, d, a, in_[ 1], S44, 2240044497U); /* 56 */ 268 II ( a, b, c, d, in_[ 8], S41, 1873313359U); /* 57 */ 269 II ( d, a, b, c, in_[15], S42, 4264355552U); /* 58 */ 270 II ( c, d, a, b, in_[ 6], S43, 2734768916U); /* 59 */ 271 II ( b, c, d, a, in_[13], S44, 1309151649U); /* 60 */ 272 II ( a, b, c, d, in_[ 4], S41, 4149444226U); /* 61 */ 273 II ( d, a, b, c, in_[11], S42, 3174756917U); /* 62 */ 274 II ( c, d, a, b, in_[ 2], S43, 718787259U); /* 63 */ 275 II ( b, c, d, a, in_[ 9], S44, 3951481745U); /* 64 */ 276 277 buf[0] += a; 278 buf[1] += b; 279 buf[2] += c; 280 buf[3] += d; 281 } 282 283 /* 284 ********************************************************************** 285 ** End of md5.c ** 286 ******************************* (cut) ******************************** 287 */