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  */