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