Correct code for mode 100 mangler
[hashcat.git] / OpenCL / mangle.cl
1 #define _MD5_
2
3 #include "inc_hash_constants.h"
4 #include "inc_hash_functions.cl"
5
6 // Domain to use for mangling
7 __constant u8 domain[] = "linkedin.com";
8 __constant u32x domain_len = 12;
9
10 // Characters used for base64 encoding
11 __constant char b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12
13 // Perform an MD5 transform step
14 // Should be called through hmac_md5_pad_mangle and hmac_md5_run_mangle
15 void md5_transform_mangle (const u32x w0[4], const u32x w1[4], const u32x w2[4], const u32x w3[4], u32x digest[4])
16 {
17   u32x a = digest[0];
18   u32x b = digest[1];
19   u32x c = digest[2];
20   u32x d = digest[3];
21
22   u32x w0_t = w0[0];
23   u32x w1_t = w0[1];
24   u32x w2_t = w0[2];
25   u32x w3_t = w0[3];
26   u32x w4_t = w1[0];
27   u32x w5_t = w1[1];
28   u32x w6_t = w1[2];
29   u32x w7_t = w1[3];
30   u32x w8_t = w2[0];
31   u32x w9_t = w2[1];
32   u32x wa_t = w2[2];
33   u32x wb_t = w2[3];
34   u32x wc_t = w3[0];
35   u32x wd_t = w3[1];
36   u32x we_t = w3[2];
37   u32x wf_t = w3[3];
38
39   MD5_STEP (MD5_Fo, a, b, c, d, w0_t, MD5C00, MD5S00);
40   MD5_STEP (MD5_Fo, d, a, b, c, w1_t, MD5C01, MD5S01);
41   MD5_STEP (MD5_Fo, c, d, a, b, w2_t, MD5C02, MD5S02);
42   MD5_STEP (MD5_Fo, b, c, d, a, w3_t, MD5C03, MD5S03);
43   MD5_STEP (MD5_Fo, a, b, c, d, w4_t, MD5C04, MD5S00);
44   MD5_STEP (MD5_Fo, d, a, b, c, w5_t, MD5C05, MD5S01);
45   MD5_STEP (MD5_Fo, c, d, a, b, w6_t, MD5C06, MD5S02);
46   MD5_STEP (MD5_Fo, b, c, d, a, w7_t, MD5C07, MD5S03);
47   MD5_STEP (MD5_Fo, a, b, c, d, w8_t, MD5C08, MD5S00);
48   MD5_STEP (MD5_Fo, d, a, b, c, w9_t, MD5C09, MD5S01);
49   MD5_STEP (MD5_Fo, c, d, a, b, wa_t, MD5C0a, MD5S02);
50   MD5_STEP (MD5_Fo, b, c, d, a, wb_t, MD5C0b, MD5S03);
51   MD5_STEP (MD5_Fo, a, b, c, d, wc_t, MD5C0c, MD5S00);
52   MD5_STEP (MD5_Fo, d, a, b, c, wd_t, MD5C0d, MD5S01);
53   MD5_STEP (MD5_Fo, c, d, a, b, we_t, MD5C0e, MD5S02);
54   MD5_STEP (MD5_Fo, b, c, d, a, wf_t, MD5C0f, MD5S03);
55
56   MD5_STEP (MD5_Go, a, b, c, d, w1_t, MD5C10, MD5S10);
57   MD5_STEP (MD5_Go, d, a, b, c, w6_t, MD5C11, MD5S11);
58   MD5_STEP (MD5_Go, c, d, a, b, wb_t, MD5C12, MD5S12);
59   MD5_STEP (MD5_Go, b, c, d, a, w0_t, MD5C13, MD5S13);
60   MD5_STEP (MD5_Go, a, b, c, d, w5_t, MD5C14, MD5S10);
61   MD5_STEP (MD5_Go, d, a, b, c, wa_t, MD5C15, MD5S11);
62   MD5_STEP (MD5_Go, c, d, a, b, wf_t, MD5C16, MD5S12);
63   MD5_STEP (MD5_Go, b, c, d, a, w4_t, MD5C17, MD5S13);
64   MD5_STEP (MD5_Go, a, b, c, d, w9_t, MD5C18, MD5S10);
65   MD5_STEP (MD5_Go, d, a, b, c, we_t, MD5C19, MD5S11);
66   MD5_STEP (MD5_Go, c, d, a, b, w3_t, MD5C1a, MD5S12);
67   MD5_STEP (MD5_Go, b, c, d, a, w8_t, MD5C1b, MD5S13);
68   MD5_STEP (MD5_Go, a, b, c, d, wd_t, MD5C1c, MD5S10);
69   MD5_STEP (MD5_Go, d, a, b, c, w2_t, MD5C1d, MD5S11);
70   MD5_STEP (MD5_Go, c, d, a, b, w7_t, MD5C1e, MD5S12);
71   MD5_STEP (MD5_Go, b, c, d, a, wc_t, MD5C1f, MD5S13);
72
73   MD5_STEP (MD5_H, a, b, c, d, w5_t, MD5C20, MD5S20);
74   MD5_STEP (MD5_H, d, a, b, c, w8_t, MD5C21, MD5S21);
75   MD5_STEP (MD5_H, c, d, a, b, wb_t, MD5C22, MD5S22);
76   MD5_STEP (MD5_H, b, c, d, a, we_t, MD5C23, MD5S23);
77   MD5_STEP (MD5_H, a, b, c, d, w1_t, MD5C24, MD5S20);
78   MD5_STEP (MD5_H, d, a, b, c, w4_t, MD5C25, MD5S21);
79   MD5_STEP (MD5_H, c, d, a, b, w7_t, MD5C26, MD5S22);
80   MD5_STEP (MD5_H, b, c, d, a, wa_t, MD5C27, MD5S23);
81   MD5_STEP (MD5_H, a, b, c, d, wd_t, MD5C28, MD5S20);
82   MD5_STEP (MD5_H, d, a, b, c, w0_t, MD5C29, MD5S21);
83   MD5_STEP (MD5_H, c, d, a, b, w3_t, MD5C2a, MD5S22);
84   MD5_STEP (MD5_H, b, c, d, a, w6_t, MD5C2b, MD5S23);
85   MD5_STEP (MD5_H, a, b, c, d, w9_t, MD5C2c, MD5S20);
86   MD5_STEP (MD5_H, d, a, b, c, wc_t, MD5C2d, MD5S21);
87   MD5_STEP (MD5_H, c, d, a, b, wf_t, MD5C2e, MD5S22);
88   MD5_STEP (MD5_H, b, c, d, a, w2_t, MD5C2f, MD5S23);
89
90   MD5_STEP (MD5_I, a, b, c, d, w0_t, MD5C30, MD5S30);
91   MD5_STEP (MD5_I, d, a, b, c, w7_t, MD5C31, MD5S31);
92   MD5_STEP (MD5_I, c, d, a, b, we_t, MD5C32, MD5S32);
93   MD5_STEP (MD5_I, b, c, d, a, w5_t, MD5C33, MD5S33);
94   MD5_STEP (MD5_I, a, b, c, d, wc_t, MD5C34, MD5S30);
95   MD5_STEP (MD5_I, d, a, b, c, w3_t, MD5C35, MD5S31);
96   MD5_STEP (MD5_I, c, d, a, b, wa_t, MD5C36, MD5S32);
97   MD5_STEP (MD5_I, b, c, d, a, w1_t, MD5C37, MD5S33);
98   MD5_STEP (MD5_I, a, b, c, d, w8_t, MD5C38, MD5S30);
99   MD5_STEP (MD5_I, d, a, b, c, wf_t, MD5C39, MD5S31);
100   MD5_STEP (MD5_I, c, d, a, b, w6_t, MD5C3a, MD5S32);
101   MD5_STEP (MD5_I, b, c, d, a, wd_t, MD5C3b, MD5S33);
102   MD5_STEP (MD5_I, a, b, c, d, w4_t, MD5C3c, MD5S30);
103   MD5_STEP (MD5_I, d, a, b, c, wb_t, MD5C3d, MD5S31);
104   MD5_STEP (MD5_I, c, d, a, b, w2_t, MD5C3e, MD5S32);
105   MD5_STEP (MD5_I, b, c, d, a, w9_t, MD5C3f, MD5S33);
106
107   digest[0] += a;
108   digest[1] += b;
109   digest[2] += c;
110   digest[3] += d;
111 }
112
113 // Set up the HMAC-MD5 process
114 // The ipad and opad arrays can be retained to run multiple HMAC-MD5 processes
115 // without having to recalculate
116 // w0, w1, w2, w3 - contain up to 64 bytes of the HMAC key
117 // ipad, opad - contain the returned data to pass into the next call
118 void hmac_md5_pad_mangle (u32x w0[4], u32x w1[4], u32x w2[4], u32x w3[4], u32x ipad[4], u32x opad[4])
119 {
120   w0[0] = w0[0] ^ 0x36363636;
121   w0[1] = w0[1] ^ 0x36363636;
122   w0[2] = w0[2] ^ 0x36363636;
123   w0[3] = w0[3] ^ 0x36363636;
124   w1[0] = w1[0] ^ 0x36363636;
125   w1[1] = w1[1] ^ 0x36363636;
126   w1[2] = w1[2] ^ 0x36363636;
127   w1[3] = w1[3] ^ 0x36363636;
128   w2[0] = w2[0] ^ 0x36363636;
129   w2[1] = w2[1] ^ 0x36363636;
130   w2[2] = w2[2] ^ 0x36363636;
131   w2[3] = w2[3] ^ 0x36363636;
132   w3[0] = w3[0] ^ 0x36363636;
133   w3[1] = w3[1] ^ 0x36363636;
134   w3[2] = w3[2] ^ 0x36363636;
135   w3[3] = w3[3] ^ 0x36363636;
136
137   ipad[0] = MD5M_A;
138   ipad[1] = MD5M_B;
139   ipad[2] = MD5M_C;
140   ipad[3] = MD5M_D;
141
142   md5_transform_mangle (w0, w1, w2, w3, ipad);
143
144   w0[0] = w0[0] ^ 0x6a6a6a6a;
145   w0[1] = w0[1] ^ 0x6a6a6a6a;
146   w0[2] = w0[2] ^ 0x6a6a6a6a;
147   w0[3] = w0[3] ^ 0x6a6a6a6a;
148   w1[0] = w1[0] ^ 0x6a6a6a6a;
149   w1[1] = w1[1] ^ 0x6a6a6a6a;
150   w1[2] = w1[2] ^ 0x6a6a6a6a;
151   w1[3] = w1[3] ^ 0x6a6a6a6a;
152   w2[0] = w2[0] ^ 0x6a6a6a6a;
153   w2[1] = w2[1] ^ 0x6a6a6a6a;
154   w2[2] = w2[2] ^ 0x6a6a6a6a;
155   w2[3] = w2[3] ^ 0x6a6a6a6a;
156   w3[0] = w3[0] ^ 0x6a6a6a6a;
157   w3[1] = w3[1] ^ 0x6a6a6a6a;
158   w3[2] = w3[2] ^ 0x6a6a6a6a;
159   w3[3] = w3[3] ^ 0x6a6a6a6a;
160
161   opad[0] = MD5M_A;
162   opad[1] = MD5M_B;
163   opad[2] = MD5M_C;
164   opad[3] = MD5M_D;
165
166   md5_transform_mangle (w0, w1, w2, w3, opad);
167 }
168
169 // Continue the HMAC-MD5 process
170 // It's up to the caller to add the final length and padding terminators
171 // hmac_md5_pad_mangle call, which can be used across multiple HMACs
172 // w0, w1, w2, w3 - contain up to 64 bytes of data to HMAC
173 // ipad, opad - should contain the output from the 
174 // digest - the 16-byte result of the HMAC
175 void hmac_md5_run_mangle (u32x w0[4], u32x w1[4], u32x w2[4], u32x w3[4], u32x ipad[4], u32x opad[4], u32x digest[4])
176 {
177   digest[0] = ipad[0];
178   digest[1] = ipad[1];
179   digest[2] = ipad[2];
180   digest[3] = ipad[3];
181
182   md5_transform_mangle (w0, w1, w2, w3, digest);
183
184   w0[0] = digest[0];
185   w0[1] = digest[1];
186   w0[2] = digest[2];
187   w0[3] = digest[3];
188   w1[0] = 0x80;
189   w1[1] = 0;
190   w1[2] = 0;
191   w1[3] = 0;
192   w2[0] = 0;
193   w2[1] = 0;
194   w2[2] = 0;
195   w2[3] = 0;
196   w3[0] = 0;
197   w3[1] = 0;
198   w3[2] = (64 + 16) * 8;
199   w3[3] = 0;
200
201   digest[0] = opad[0];
202   digest[1] = opad[1];
203   digest[2] = opad[2];
204   digest[3] = opad[3];
205
206   md5_transform_mangle (w0, w1, w2, w3, digest);
207 }
208
209 // Perfrom an HMAC-MD5 with the given key and using the domain constant as the
210 // data to HMAC
211 // in_key - the key to use (the user's password)
212 // key-len - the length of the key in bytes
213 // out_digest - returns the 16 byte result
214 void md5hmac_domain_mangle (u8 const *const in_key, const u32x key_len, u8 out_digest[16])
215 {
216   u32 pos;
217
218   // Data
219   u32x data_buf[16];
220
221   for (pos = 0; pos < domain_len; pos++)
222   {
223     ((u8 *) data_buf)[pos] = domain[pos];
224   }
225   for (pos = domain_len; pos < 64; pos++)
226   {
227     ((u8 *) data_buf)[pos] = 0;
228   }
229
230   // Key
231   u32x key_buf[16];
232
233   for (pos = 0; pos < key_len; pos++)
234   {
235     ((u8 *) key_buf)[pos] = in_key[pos];
236   }
237   for (pos = key_len; pos < 64; pos++)
238   {
239     ((u8 *) key_buf)[pos] = 0;
240   }
241
242   // Pads
243   u32x ipad[4];
244   u32x opad[4];
245
246   hmac_md5_pad_mangle (key_buf, key_buf + 4, key_buf + 8, key_buf + 12, ipad, opad);
247
248   // Loop (except this time we don't actually loop)
249   append_0x80_2x4_VV (data_buf, data_buf + 4, domain_len);
250
251   data_buf[14] = (64 + domain_len) * 8;
252
253   hmac_md5_run_mangle (data_buf, data_buf + 4, data_buf + 8, data_buf + 12, ipad, opad, (u32x *) out_digest);
254 }
255
256 // Base64 encode a string
257 // base64_hash - the returned hahs
258 // len - the length of the input string
259 // base64_plain - the string to encode
260 // returns the length of the final encoding
261 u32 b64_encode_mangle (u8 * base64_hash, const u32 len, const u8 * base64_plain)
262 {
263   u8 *out_ptr = (u8 *) base64_hash;
264   u8 *in_ptr = (u8 *) base64_plain;
265   u32 out_len;
266
267   u32 i;
268
269   // Encode the easy iniitial characters
270   out_len = 0;
271   for (i = 0; i < (len - 2); i += 3)
272   {
273     char out_val0 = b64_table[((in_ptr[0] >> 2) & 0x3f)];
274     char out_val1 = b64_table[((in_ptr[0] << 4) & 0x30) | ((in_ptr[1] >> 4) & 0x0f)];
275     char out_val2 = b64_table[((in_ptr[1] << 2) & 0x3c) | ((in_ptr[2] >> 6) & 0x03)];
276     char out_val3 = b64_table[((in_ptr[2] >> 0) & 0x3f)];
277
278     out_ptr[0] = out_val0 & 0x7f;
279     out_ptr[1] = out_val1 & 0x7f;
280     out_ptr[2] = out_val2 & 0x7f;
281     out_ptr[3] = out_val3 & 0x7f;
282
283     in_ptr += 3;
284     out_ptr += 4;
285     out_len += 4;
286   }
287   // Deal with the awkward terminating characters if there are any
288   if (i == (len - 1))
289   {
290     // Input string has one hanging character
291     char out_val0 = b64_table[((in_ptr[0] >> 2) & 0x3f)];
292     char out_val1 = b64_table[((in_ptr[0] << 4) & 0x30)];
293
294     out_ptr[0] = out_val0 & 0x7f;
295     out_ptr[1] = out_val1 & 0x7f;
296     out_ptr[2] = '=';
297     out_ptr[3] = '=';
298
299     in_ptr += 3;
300     out_ptr += 4;
301     out_len += 4;
302   }
303   if (i == (len - 2))
304   {
305     // Input string has two hanging characters
306     char out_val0 = b64_table[((in_ptr[0] >> 2) & 0x3f)];
307     char out_val1 = b64_table[((in_ptr[0] << 4) & 0x30) | ((in_ptr[1] >> 4) & 0x0f)];
308     char out_val2 = b64_table[((in_ptr[1] << 2) & 0x3c)];
309
310     out_ptr[0] = out_val0 & 0x7f;
311     out_ptr[1] = out_val1 & 0x7f;
312     out_ptr[2] = out_val2 & 0x7f;
313     out_ptr[3] = '=';
314
315     in_ptr += 3;
316     out_ptr += 4;
317     out_len += 4;
318   }
319
320   return out_len;
321 }
322
323 // Determine whether a given string contains non-alphanumeric values
324 // A non-alphanumeric is anything except a-z, A-Z, 0-9
325 // data - the string to check
326 // length - the length of the string
327 // returns true if there's a non-alphanumeric value, false o/w
328 bool containsnonalphanumeric_mangle (u8 * data, u32 length)
329 {
330   bool nonalphanumeric;
331   u32 pos;
332   char check;
333   u32 startingSize;
334
335   nonalphanumeric = false;
336   // Check each character individually
337   for (pos = 0; (pos < length) && !nonalphanumeric; pos++)
338   {
339     check = data[pos];
340     if (!((check >= 'a') && (check <= 'z')) && !((check >= 'A') && (check <= 'Z')) && !((check >= '0') && (check <= '9')) && !(check == '_'))
341     {
342       nonalphanumeric = true;
343     }
344   }
345
346   return nonalphanumeric;
347 }
348
349 // Determine whether a string contains any value between a given range
350 // password - the string to check
351 // length - the length of the string to check
352 // start - the inclusive lower bound of the range to check between
353 // end - the inclusive upper bound of the range to check between
354 // returns true if the string contains a value that falls in the range
355 // returns false o/w
356 bool contains_mangle (u8 const *password, u32 length, u8 start, u8 end)
357 {
358   bool doescontain = false;
359   u32 pos;
360
361   // Check each character individually
362   for (pos = 0; (pos < length) && (doescontain == false); pos++)
363   {
364     if ((password[pos] >= start) && (password[pos] <= end))
365     {
366       doescontain = true;
367     }
368   }
369
370   return doescontain;
371 }
372
373 // Rotate the characters in a string to the left by the given number of
374 // characters
375 // torotate - the string to rotate
376 // length - the length of the string to rotate
377 // steps - the number of steps to rotate to the left by
378 void rotate_string_mangle (u8 * torotate, u32 length, u32 steps)
379 {
380   u8 scratch[64];
381   u32 pos;
382
383   // Create a rotated copy in a temporary buffer
384   for (pos = 0; pos < length; pos++)
385   {
386     scratch[pos] = torotate[(pos + steps) % length];
387   }
388
389   // Copy the result back into the original buffer
390   for (pos = 0; pos < length; pos++)
391   {
392     torotate[pos] = scratch[pos];
393   }
394 }
395
396 // Perform the mangle operation on the string to be hashed
397 // w0, w1 - the string to be mangled
398 // in_len - the length of the string to be mangled
399 u32x mangle (u32x w0[4], u32x w1[4], const u32x in_len)
400 {
401   u32x out_len = in_len;
402
403   u32 digest[4];
404   u32 data[8];
405   u32 hash[8];
406   u32 i;
407   u32 size;
408   u32 extrasize;
409   u32 startingsize;
410   bool nonalphanumeric;
411   u32 extrapos;
412   u8 next;
413
414   hash[0] = w0[0];
415   hash[1] = w0[1];
416   hash[2] = w0[2];
417   hash[3] = w0[3];
418   hash[4] = w1[0];
419   hash[5] = w1[1];
420   hash[6] = w1[2];
421   hash[7] = w1[3];
422
423   // HMAC-MD5 the domain name using the password as the key
424   md5hmac_domain_mangle ((u8 *) hash, in_len, (u8 *) digest);
425
426   // Check whether the original password contains non-alphanumeric values
427   nonalphanumeric = containsnonalphanumeric_mangle ((u8 *) hash, in_len);
428
429   w0[0] = digest[0];
430   w0[1] = digest[1];
431   w0[2] = digest[2];
432   w0[3] = digest[3];
433   w1[0] = 0;
434   w1[1] = 0;
435   w1[2] = 0;
436   w1[3] = 0;
437
438   // Base64 encode the HMAC; this will be what we use to generate the password
439   out_len = b64_encode_mangle ((u8 *) hash, 16, (u8 *) w0);
440
441   out_len = 22;                 // b64 encoding will produce 24 bytes output, but last two will be "=="
442   extrasize = 22;
443   size = in_len + 2;
444
445   // for (i = out_len; i < 32; i++) {
446   // ((u8 *)hash)[i] = 0;
447   // }
448
449   startingsize = size - 4;
450   startingsize = (startingsize < extrasize) ? startingsize : extrasize;
451
452   // Transfer the intial portion for output
453   for (i = 0; i < startingsize; i++)
454   {
455     ((u8 *) data)[i] = ((u8 *) hash)[i];
456   }
457   for (i = startingsize; i < 32; i++)
458   {
459     ((u8 *) data)[i] = 0;
460   }
461
462   extrapos = startingsize;
463
464   // Add the extras
465   // Capital letter
466   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
467   extrapos++;
468   if (!contains_mangle ((u8 *) data, startingsize, 'A', 'Z'))
469   {
470     next = 'A' + (next % ('Z' - 'A' + 1));
471   }
472   ((u8 *) data)[startingsize] = next;
473   startingsize++;
474
475   // Lower case letter
476   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
477   extrapos++;
478   if (!contains_mangle ((u8 *) data, startingsize, 'a', 'z'))
479   {
480     next = 'a' + (next % ('z' - 'a' + 1));
481   }
482   ((u8 *) data)[startingsize] = next;
483   startingsize++;
484
485   // Number
486   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
487   extrapos++;
488   if (!contains_mangle ((u8 *) data, startingsize, '0', '9'))
489   {
490     next = '0' + (next % ('9' - '0' + 1));
491   }
492   ((u8 *) data)[startingsize] = next;
493   startingsize++;
494
495   // Non alphanumeric
496   if (containsnonalphanumeric_mangle ((u8 *) data, startingsize) && nonalphanumeric)
497   {
498     next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
499     extrapos++;
500   }
501   else
502   {
503     next = '+';
504   }
505   ((u8 *) data)[startingsize] = next;
506   startingsize++;
507
508   // If there's no alphanumeric values in the original password
509   // remove them from the result
510   if (!nonalphanumeric)
511   {
512     for (i = 0; i < startingsize; i++)
513     {
514       if (containsnonalphanumeric_mangle (((u8 *) data) + i, 1))
515       {
516         next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
517         extrapos++;
518         next = 'A' + (next % ('Z' - 'A' + 1));
519         ((u8 *) data)[i] = next;
520       }
521     }
522   }
523
524   // Rotate the result to ranomise where the non-alphanumerics are
525   next = (extrapos < extrasize) ? ((u8 *) hash)[extrapos] : 0;
526   rotate_string_mangle ((u8 *) data, startingsize, next);
527   ((u8 *) data)[startingsize] = 0;
528
529   out_len = startingsize;
530
531   // Copy th result into the output buffer
532   w0[0] = data[0];
533   w0[1] = data[1];
534   w0[2] = data[2];
535   w0[3] = data[3];
536   w1[0] = data[4];
537   w1[1] = data[5];
538   w1[2] = data[6];
539   w1[3] = data[7];
540
541   return (out_len);
542 }