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