fixed problem with -m 5600 = NetNTLMv2 parser
[hashcat.git] / src / shared.c
index 16f8abb..f1002b7 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * Authors.....: Jens Steube <jens.steube@gmail.com>
  *               Gabriele Gristina <matrix@hashcat.net>
+ *               magnum <john.magnum@hushmail.com>
  *
  * License.....: MIT
  */
 #include <shared.h>
 #include <limits.h>
 
-/**
- * tuning tools
- */
-
-#define GET_ACCEL(x) KERNEL_ACCEL_ ## x
-#define GET_LOOPS(x) KERNEL_LOOPS_ ## x
-
-#define GET_LOOPS_OSX(x) KERNEL_LOOPS_OSX_ ## x
-#define GET_ACCEL_OSX(x) KERNEL_ACCEL_OSX_ ## x
-
 /**
  * basic bit handling
  */
 
+u32 is_power_of_2(u32 v)
+{
+  return (v && !(v & (v - 1)));
+}
+
 u32 rotl32 (const u32 a, const u32 n)
 {
   return ((a << n) | (a >> (32 - n)));
@@ -3097,7 +3093,7 @@ int hm_get_temperature_with_device_id (const uint device_id)
     #if defined(LINUX) && defined(HAVE_NVML)
     int temperature = 0;
 
-    hm_NVML_nvmlDeviceGetTemperature (data.hm_nv, data.hm_device[device_id].adapter_index.nv, NVML_TEMPERATURE_GPU, (unsigned int *) &temperature);
+    hm_NVML_nvmlDeviceGetTemperature (data.hm_nv, data.hm_device[device_id].adapter_index.nv, NVML_TEMPERATURE_GPU, (uint *) &temperature);
 
     return temperature;
     #endif
@@ -3166,7 +3162,7 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
       #if defined(LINUX) && defined(HAVE_NVML)
       int speed = 0;
 
-      hm_NVML_nvmlDeviceGetFanSpeed (data.hm_nv, 1, data.hm_device[device_id].adapter_index.nv, (unsigned int *) &speed);
+      hm_NVML_nvmlDeviceGetFanSpeed (data.hm_nv, 1, data.hm_device[device_id].adapter_index.nv, (uint *) &speed);
 
       return speed;
       #endif
@@ -4197,6 +4193,35 @@ char *get_session_dir (const char *profile_dir)
   return session_dir;
 }
 
+uint count_lines (FILE *fd)
+{
+  uint cnt = 0;
+
+  char *buf = (char *) mymalloc (BUFSIZ + 1);
+
+  char prev = '\n';
+
+  while (!feof (fd))
+  {
+    size_t nread = fread (buf, sizeof (char), BUFSIZ, fd);
+
+    if (nread < 1) continue;
+
+    size_t i;
+
+    for (i = 0; i < nread; i++)
+    {
+      if (prev == '\n') cnt++;
+
+      prev = buf[i];
+    }
+  }
+
+  myfree (buf);
+
+  return cnt;
+}
+
 void truecrypt_crc32 (const char *filename, u8 keytab[64])
 {
   uint crc = ~0;
@@ -4329,6 +4354,14 @@ void *rulefind (const void *key, void *base, int nmemb, size_t size, int (*compa
   return NULL;
 }
 
+int sort_by_u32 (const void *v1, const void *v2)
+{
+  const u32 *s1 = (const u32 *) v1;
+  const u32 *s2 = (const u32 *) v2;
+
+  return *s1 - *s2;
+}
+
 int sort_by_salt (const void *v1, const void *v2)
 {
   const salt_t *s1 = (const salt_t *) v1;
@@ -4737,6 +4770,40 @@ int sort_by_digest_p0p1 (const void *v1, const void *v2)
   return (0);
 }
 
+int sort_by_tuning_db_alias (const void *v1, const void *v2)
+{
+  const tuning_db_alias_t *t1 = (const tuning_db_alias_t *) v1;
+  const tuning_db_alias_t *t2 = (const tuning_db_alias_t *) v2;
+
+  const int res1 = strcmp (t1->device_name, t2->device_name);
+
+  if (res1 != 0) return (res1);
+
+  return 0;
+}
+
+int sort_by_tuning_db_entry (const void *v1, const void *v2)
+{
+  const tuning_db_entry_t *t1 = (const tuning_db_entry_t *) v1;
+  const tuning_db_entry_t *t2 = (const tuning_db_entry_t *) v2;
+
+  const int res1 = strcmp (t1->device_name, t2->device_name);
+
+  if (res1 != 0) return (res1);
+
+  const int res2 = t1->attack_mode
+                 - t2->attack_mode;
+
+  if (res2 != 0) return (res2);
+
+  const int res3 = t1->hash_type
+                 - t2->hash_type;
+
+  if (res3 != 0) return (res3);
+
+  return 0;
+}
+
 void format_debug (char *debug_file, uint debug_mode, unsigned char *orig_plain_ptr, uint orig_plain_len, unsigned char *mod_plain_ptr, uint mod_plain_len, char *rule_buf, int rule_len)
 {
   uint outfile_autohex = data.outfile_autohex;
@@ -5781,6 +5848,9 @@ char *strhashtype (const uint hash_mode)
     case 12800: return ((char *) HT_12800); break;
     case 12900: return ((char *) HT_12900); break;
     case 13000: return ((char *) HT_13000); break;
+    case 13100: return ((char *) HT_13100); break;
+    case 13200: return ((char *) HT_13200); break;
+    case 13300: return ((char *) HT_13300); break;
   }
 
   return ((char *) "Unknown");
@@ -5800,6 +5870,7 @@ char *strstatus (const uint devices_status)
     case  STATUS_QUIT:               return ((char *) ST_0007); break;
     case  STATUS_BYPASS:             return ((char *) ST_0008); break;
     case  STATUS_STOP_AT_CHECKPOINT: return ((char *) ST_0009); break;
+    case  STATUS_AUTOTUNE:           return ((char *) ST_0010); break;
   }
 
   return ((char *) "Unknown");
@@ -8224,6 +8295,59 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       byte_swap_32 (digest_buf[1])
     );
   }
+  else if (hash_mode == 13100)
+  {
+    krb5tgs_t *krb5tgss = (krb5tgs_t *) data.esalts_buf;
+
+    krb5tgs_t *krb5tgs = &krb5tgss[salt_pos];
+
+    u8 *ptr_checksum  = (u8 *) krb5tgs->checksum;
+    u8 *ptr_edata2 = (u8 *) krb5tgs->edata2;
+
+    char data[2560 * 4 * 2] = { 0 };
+
+    char *ptr_data = data;
+
+    for (uint i = 0; i < 16; i++, ptr_data += 2)
+      sprintf (ptr_data, "%02x", ptr_checksum[i]);
+
+    /* skip '$' */
+    ptr_data++;
+
+    for (uint i = 0; i < krb5tgs->edata2_len; i++, ptr_data += 2)
+      sprintf (ptr_data, "%02x", ptr_edata2[i]);
+
+    snprintf (out_buf, len-1, "%s$%s$%s$%s",
+      SIGNATURE_KRB5TGS,
+      (char *) krb5tgs->account_info,
+      data,
+      data + 33);
+  }
+  else if (hash_mode == 13200)
+  {
+    snprintf (out_buf, len-1, "%s*%d*%08x%08x%08x%08x*%08x%08x%08x%08x%08x%08x",
+      SIGNATURE_AXCRYPT,
+      salt.salt_iter,
+      salt.salt_buf[0],
+      salt.salt_buf[1],
+      salt.salt_buf[2],
+      salt.salt_buf[3],
+      salt.salt_buf[4],
+      salt.salt_buf[5],
+      salt.salt_buf[6],
+      salt.salt_buf[7],
+      salt.salt_buf[8],
+      salt.salt_buf[9]);
+  }
+  else if (hash_mode == 13300)
+  {
+    snprintf (out_buf, len-1, "%s$%08x%08x%08x%08x",
+      SIGNATURE_AXCRYPT_SHA1,
+              digest_buf[0],
+              digest_buf[1],
+              digest_buf[2],
+              digest_buf[3]);
+  }
   else
   {
     if (hash_type == HASH_TYPE_MD4)
@@ -8994,580 +9118,306 @@ void check_checkpoint ()
 }
 
 /**
- * adjustments
+ * tuning db
  */
 
-#ifdef OSX
-uint set_kernel_accel_osx (uint hash_mode)
+void tuning_db_destroy (tuning_db_t *tuning_db)
 {
-  switch (hash_mode)
+  int i;
+
+  for (i = 0; i < tuning_db->alias_cnt; i++)
   {
-    case 1800: return GET_ACCEL_OSX (1800);
-    case 2500: return GET_ACCEL_OSX (2500);
-    case 5000: return GET_ACCEL_OSX (5000);
-    case 6100: return GET_ACCEL_OSX (6100);
-    case 6211: return GET_ACCEL_OSX (6211);
-    case 6231: return GET_ACCEL_OSX (6231);
-    case 6241: return GET_ACCEL_OSX (6241);
-    case 6800: return GET_ACCEL_OSX (6800);
-    case 7100: return GET_ACCEL_OSX (7100);
-    case 7200: return GET_ACCEL_OSX (7200);
-    case 7900: return GET_ACCEL_OSX (7900);
-    case 8200: return GET_ACCEL_OSX (8200);
-    case 8700: return GET_ACCEL_OSX (8700);
-    case 9100: return GET_ACCEL_OSX (9100);
-    case 9200: return GET_ACCEL_OSX (9200);
-    case 9300: return GET_ACCEL_OSX (9300);
-    case 9400: return GET_ACCEL_OSX (9400);
-    case 9500: return GET_ACCEL_OSX (9500);
-    case 9600: return GET_ACCEL_OSX (9600);
-    case 10000: return GET_ACCEL_OSX (10000);
-    case 10500: return GET_ACCEL_OSX (10500);
-    case 11300: return GET_ACCEL_OSX (11300);
-    case 11600: return GET_ACCEL_OSX (11600);
-    case 11700: return GET_ACCEL_OSX (11700);
-    case 11800: return GET_ACCEL_OSX (11800);
-    case 12200: return GET_ACCEL_OSX (12200);
-    case 12400: return GET_ACCEL_OSX (12400);
-    case 12500: return GET_ACCEL_OSX (12500);
-    case 13000: return GET_ACCEL_OSX (13000);
+    tuning_db_alias_t *alias = &tuning_db->alias_buf[i];
+
+    myfree (alias->device_name);
+    myfree (alias->alias_name);
   }
 
-  return (-1);
+  for (i = 0; i < tuning_db->entry_cnt; i++)
+  {
+    tuning_db_entry_t *entry = &tuning_db->entry_buf[i];
+
+    myfree (entry->device_name);
+  }
+
+  myfree (tuning_db->alias_buf);
+  myfree (tuning_db->entry_buf);
+
+  myfree (tuning_db);
 }
 
-uint set_kernel_accel (uint hash_mode, bool isGpu)
+tuning_db_t *tuning_db_alloc (FILE *fp)
 {
-  int accel = -1;
+  tuning_db_t *tuning_db = (tuning_db_t *) mymalloc (sizeof (tuning_db_t));
 
-  if (isGpu)
-    accel = set_kernel_accel_osx (hash_mode);
+  int num_lines = count_lines (fp);
 
-  if (accel != -1)
-    return accel;
-#else
+  // a bit over-allocated
+
+  tuning_db->alias_buf = (tuning_db_alias_t *) mycalloc (num_lines + 1, sizeof (tuning_db_alias_t));
+  tuning_db->alias_cnt = 0;
 
-uint set_kernel_accel (uint hash_mode)
+  tuning_db->entry_buf = (tuning_db_entry_t *) mycalloc (num_lines + 1, sizeof (tuning_db_entry_t));
+  tuning_db->entry_cnt = 0;
+
+  return tuning_db;
+}
+
+tuning_db_t *tuning_db_init (const char *tuning_db_file)
 {
+  FILE *fp = fopen (tuning_db_file, "rb");
 
-#endif
+  if (fp == NULL)
+  {
+    log_error ("%s: %s", tuning_db_file, strerror (errno));
 
-  switch (hash_mode)
+    exit (-1);
+  }
+
+  tuning_db_t *tuning_db = tuning_db_alloc (fp);
+
+  rewind (fp);
+
+  int line_num = 0;
+
+  while (!feof (fp))
   {
-    case     0: return GET_ACCEL (0);
-    case    10: return GET_ACCEL (10);
-    case    11: return GET_ACCEL (11);
-    case    12: return GET_ACCEL (12);
-    case    20: return GET_ACCEL (20);
-    case    21: return GET_ACCEL (21);
-    case    22: return GET_ACCEL (22);
-    case    23: return GET_ACCEL (23);
-    case    30: return GET_ACCEL (30);
-    case    40: return GET_ACCEL (40);
-    case    50: return GET_ACCEL (50);
-    case    60: return GET_ACCEL (60);
-    case   100: return GET_ACCEL (100);
-    case   101: return GET_ACCEL (101);
-    case   110: return GET_ACCEL (110);
-    case   111: return GET_ACCEL (111);
-    case   112: return GET_ACCEL (112);
-    case   120: return GET_ACCEL (120);
-    case   121: return GET_ACCEL (121);
-    case   122: return GET_ACCEL (122);
-    case   124: return GET_ACCEL (124);
-    case   130: return GET_ACCEL (130);
-    case   131: return GET_ACCEL (131);
-    case   132: return GET_ACCEL (132);
-    case   133: return GET_ACCEL (133);
-    case   140: return GET_ACCEL (140);
-    case   141: return GET_ACCEL (141);
-    case   150: return GET_ACCEL (150);
-    case   160: return GET_ACCEL (160);
-    case   190: return GET_ACCEL (190);
-    case   200: return GET_ACCEL (200);
-    case   300: return GET_ACCEL (300);
-    case   400: return GET_ACCEL (400);
-    case   500: return GET_ACCEL (500);
-    case   501: return GET_ACCEL (501);
-    case   900: return GET_ACCEL (900);
-    case   910: return GET_ACCEL (910);
-    case  1000: return GET_ACCEL (1000);
-    case  1100: return GET_ACCEL (1100);
-    case  1400: return GET_ACCEL (1400);
-    case  1410: return GET_ACCEL (1410);
-    case  1420: return GET_ACCEL (1420);
-    case  1421: return GET_ACCEL (1421);
-    case  1430: return GET_ACCEL (1430);
-    case  1440: return GET_ACCEL (1440);
-    case  1441: return GET_ACCEL (1441);
-    case  1450: return GET_ACCEL (1450);
-    case  1460: return GET_ACCEL (1460);
-    case  1500: return GET_ACCEL (1500);
-    case  1600: return GET_ACCEL (1600);
-    case  1700: return GET_ACCEL (1700);
-    case  1710: return GET_ACCEL (1710);
-    case  1711: return GET_ACCEL (1711);
-    case  1720: return GET_ACCEL (1720);
-    case  1722: return GET_ACCEL (1722);
-    case  1730: return GET_ACCEL (1730);
-    case  1731: return GET_ACCEL (1731);
-    case  1740: return GET_ACCEL (1740);
-    case  1750: return GET_ACCEL (1750);
-    case  1760: return GET_ACCEL (1760);
-    case  1800: return GET_ACCEL (1800);
-    case  2100: return GET_ACCEL (2100);
-    case  2400: return GET_ACCEL (2400);
-    case  2410: return GET_ACCEL (2410);
-    case  2500: return GET_ACCEL (2500);
-    case  2600: return GET_ACCEL (2600);
-    case  2611: return GET_ACCEL (2611);
-    case  2612: return GET_ACCEL (2612);
-    case  2711: return GET_ACCEL (2711);
-    case  2811: return GET_ACCEL (2811);
-    case  3000: return GET_ACCEL (3000);
-    case  3100: return GET_ACCEL (3100);
-    case  3200: return GET_ACCEL (3200);
-    case  3710: return GET_ACCEL (3710);
-    case  3711: return GET_ACCEL (3711);
-    case  3800: return GET_ACCEL (3800);
-    case  4300: return GET_ACCEL (4300);
-    case  4400: return GET_ACCEL (4400);
-    case  4500: return GET_ACCEL (4500);
-    case  4700: return GET_ACCEL (4700);
-    case  4800: return GET_ACCEL (4800);
-    case  4900: return GET_ACCEL (4900);
-    case  5000: return GET_ACCEL (5000);
-    case  5100: return GET_ACCEL (5100);
-    case  5200: return GET_ACCEL (5200);
-    case  5300: return GET_ACCEL (5300);
-    case  5400: return GET_ACCEL (5400);
-    case  5500: return GET_ACCEL (5500);
-    case  5600: return GET_ACCEL (5600);
-    case  5700: return GET_ACCEL (5700);
-    case  5800: return GET_ACCEL (5800);
-    case  6000: return GET_ACCEL (6000);
-    case  6100: return GET_ACCEL (6100);
-    case  6211: return GET_ACCEL (6211);
-    case  6212: return GET_ACCEL (6212);
-    case  6213: return GET_ACCEL (6213);
-    case  6221: return GET_ACCEL (6221);
-    case  6222: return GET_ACCEL (6222);
-    case  6223: return GET_ACCEL (6223);
-    case  6231: return GET_ACCEL (6231);
-    case  6232: return GET_ACCEL (6232);
-    case  6233: return GET_ACCEL (6233);
-    case  6241: return GET_ACCEL (6241);
-    case  6242: return GET_ACCEL (6242);
-    case  6243: return GET_ACCEL (6243);
-    case  6300: return GET_ACCEL (6300);
-    case  6400: return GET_ACCEL (6400);
-    case  6500: return GET_ACCEL (6500);
-    case  6600: return GET_ACCEL (6600);
-    case  6700: return GET_ACCEL (6700);
-    case  6800: return GET_ACCEL (6800);
-    case  6900: return GET_ACCEL (6900);
-    case  7100: return GET_ACCEL (7100);
-    case  7200: return GET_ACCEL (7200);
-    case  7300: return GET_ACCEL (7300);
-    case  7400: return GET_ACCEL (7400);
-    case  7500: return GET_ACCEL (7500);
-    case  7600: return GET_ACCEL (7600);
-    case  7700: return GET_ACCEL (7700);
-    case  7800: return GET_ACCEL (7800);
-    case  7900: return GET_ACCEL (7900);
-    case  8000: return GET_ACCEL (8000);
-    case  8100: return GET_ACCEL (8100);
-    case  8200: return GET_ACCEL (8200);
-    case  8300: return GET_ACCEL (8300);
-    case  8400: return GET_ACCEL (8400);
-    case  8500: return GET_ACCEL (8500);
-    case  8600: return GET_ACCEL (8600);
-    case  8700: return GET_ACCEL (8700);
-    case  8800: return GET_ACCEL (8800);
-    case  8900: return GET_ACCEL (8900);
-    case  9000: return GET_ACCEL (9000);
-    case  9100: return GET_ACCEL (9100);
-    case  9200: return GET_ACCEL (9200);
-    case  9300: return GET_ACCEL (9300);
-    case  9400: return GET_ACCEL (9400);
-    case  9500: return GET_ACCEL (9500);
-    case  9600: return GET_ACCEL (9600);
-    case  9700: return GET_ACCEL (9700);
-    case  9710: return GET_ACCEL (9710);
-    case  9720: return GET_ACCEL (9720);
-    case  9800: return GET_ACCEL (9800);
-    case  9810: return GET_ACCEL (9810);
-    case  9820: return GET_ACCEL (9820);
-    case  9900: return GET_ACCEL (9900);
-    case 10000: return GET_ACCEL (10000);
-    case 10100: return GET_ACCEL (10100);
-    case 10200: return GET_ACCEL (10200);
-    case 10300: return GET_ACCEL (10300);
-    case 10400: return GET_ACCEL (10400);
-    case 10410: return GET_ACCEL (10410);
-    case 10420: return GET_ACCEL (10420);
-    case 10500: return GET_ACCEL (10500);
-    case 10600: return GET_ACCEL (10600);
-    case 10700: return GET_ACCEL (10700);
-    case 10800: return GET_ACCEL (10800);
-    case 10900: return GET_ACCEL (10900);
-    case 11000: return GET_ACCEL (11000);
-    case 11100: return GET_ACCEL (11100);
-    case 11200: return GET_ACCEL (11200);
-    case 11300: return GET_ACCEL (11300);
-    case 11400: return GET_ACCEL (11400);
-    case 11500: return GET_ACCEL (11500);
-    case 11600: return GET_ACCEL (11600);
-    case 11700: return GET_ACCEL (11700);
-    case 11800: return GET_ACCEL (11800);
-    case 11900: return GET_ACCEL (11900);
-    case 12000: return GET_ACCEL (12000);
-    case 12100: return GET_ACCEL (12100);
-    case 12200: return GET_ACCEL (12200);
-    case 12300: return GET_ACCEL (12300);
-    case 12400: return GET_ACCEL (12400);
-    case 12500: return GET_ACCEL (12500);
-    case 12600: return GET_ACCEL (12600);
-    case 12700: return GET_ACCEL (12700);
-    case 12800: return GET_ACCEL (12800);
-    case 12900: return GET_ACCEL (12900);
-    case 13000: return GET_ACCEL (13000);
+    char buf[BUFSIZ];
+
+    char *line_buf = fgets (buf, sizeof (buf) - 1, fp);
+
+    if (line_buf == NULL) break;
+
+    line_num++;
+
+    const int line_len = in_superchop (line_buf);
+
+    if (line_len == 0) continue;
+
+    if (line_buf[0] == '#') continue;
+
+    // start processing
+
+    char *token_ptr[7] = { NULL };
+
+    int token_cnt = 0;
+
+    char *next = strtok (line_buf, "\t ");
+
+    token_ptr[token_cnt] = next;
+
+    token_cnt++;
+
+    while ((next = strtok (NULL, "\t ")) != NULL)
+    {
+      token_ptr[token_cnt] = next;
+
+      token_cnt++;
+    }
+
+    if (token_cnt == 2)
+    {
+      char *device_name = token_ptr[0];
+      char *alias_name  = token_ptr[1];
+
+      tuning_db_alias_t *alias = &tuning_db->alias_buf[tuning_db->alias_cnt];
+
+      alias->device_name = mystrdup (device_name);
+      alias->alias_name  = mystrdup (alias_name);
+
+      tuning_db->alias_cnt++;
+    }
+    else if (token_cnt == 6)
+    {
+      if ((token_ptr[1][0] != '0') &&
+          (token_ptr[1][0] != '1') &&
+          (token_ptr[1][0] != '3') &&
+          (token_ptr[1][0] != '*'))
+      {
+        log_info ("WARNING: Tuning-db: Invalid attack_mode '%c' in Line '%u'", token_ptr[1][0], line_num);
+
+        continue;
+      }
+
+      if ((token_ptr[3][0] != '1') &&
+          (token_ptr[3][0] != '2') &&
+          (token_ptr[3][0] != '4') &&
+          (token_ptr[3][0] != '8') &&
+          (token_ptr[3][0] != 'N'))
+      {
+        log_info ("WARNING: Tuning-db: Invalid vector_width '%c' in Line '%u'", token_ptr[3][0], line_num);
+
+        continue;
+      }
+
+      char *device_name = token_ptr[0];
+
+      int attack_mode      = -1;
+      int hash_type        = -1;
+      int vector_width     = -1;
+      int kernel_accel     = -1;
+      int kernel_loops     = -1;
+
+      if (token_ptr[1][0] != '*') attack_mode      = atoi (token_ptr[1]);
+      if (token_ptr[2][0] != '*') hash_type        = atoi (token_ptr[2]);
+      if (token_ptr[3][0] != 'N') vector_width     = atoi (token_ptr[3]);
+
+      if (token_ptr[4][0] != 'A')
+      {
+        kernel_accel = atoi (token_ptr[4]);
+
+        if ((kernel_accel < 1) || (kernel_accel > 1024))
+        {
+          log_info ("WARNING: Tuning-db: Invalid kernel_accel '%d' in Line '%u'", kernel_accel, line_num);
+
+          continue;
+        }
+      }
+      else
+      {
+        kernel_accel = 0;
+      }
+
+      if (token_ptr[5][0] != 'A')
+      {
+        kernel_loops = atoi (token_ptr[5]);
+
+        if ((kernel_loops < 1) || (kernel_loops > 1024))
+        {
+          log_info ("WARNING: Tuning-db: Invalid kernel_loops '%d' in Line '%u'", kernel_loops, line_num);
+
+          continue;
+        }
+      }
+      else
+      {
+        kernel_loops = 0;
+      }
+
+      tuning_db_entry_t *entry = &tuning_db->entry_buf[tuning_db->entry_cnt];
+
+      entry->device_name  = mystrdup (device_name);
+      entry->attack_mode  = attack_mode;
+      entry->hash_type    = hash_type;
+      entry->vector_width = vector_width;
+      entry->kernel_accel = kernel_accel;
+      entry->kernel_loops = kernel_loops;
+
+      tuning_db->entry_cnt++;
+    }
+    else
+    {
+      log_info ("WARNING: Tuning-db: Invalid number of token in Line '%u'", line_num);
+
+      continue;
+    }
   }
 
-  return 0;
+  fclose (fp);
+
+  // todo: print loaded 'cnt' message
+
+  // sort the database
+
+  qsort (tuning_db->alias_buf, tuning_db->alias_cnt, sizeof (tuning_db_alias_t), sort_by_tuning_db_alias);
+  qsort (tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
+
+  return tuning_db;
 }
 
-#ifdef OSX
-uint set_kernel_loops_osx (uint hash_mode)
+tuning_db_entry_t *tuning_db_search (tuning_db_t *tuning_db, hc_device_param_t *device_param, int attack_mode, int hash_type)
 {
-  switch (hash_mode)
+  static tuning_db_entry_t s;
+
+  // first we need to convert all spaces in the device_name to underscore
+
+  char *device_name_nospace = strdup (device_param->device_name);
+
+  int device_name_length = strlen (device_name_nospace);
+
+  int i;
+
+  for (i = 0; i < device_name_length; i++)
   {
-    case 0: return GET_LOOPS_OSX (0);
-    case 10: return GET_LOOPS_OSX (10);
-    case 11: return GET_LOOPS_OSX (11);
-    case 12: return GET_LOOPS_OSX (12);
-    case 20: return GET_LOOPS_OSX (20);
-    case 21: return GET_LOOPS_OSX (21);
-    case 22: return GET_LOOPS_OSX (22);
-    case 23: return GET_LOOPS_OSX (23);
-    case 30: return GET_LOOPS_OSX (30);
-    case 40: return GET_LOOPS_OSX (40);
-    case 50: return GET_LOOPS_OSX (50);
-    case 60: return GET_LOOPS_OSX (60);
-    case 100: return GET_LOOPS_OSX (100);
-    case 101: return GET_LOOPS_OSX (101);
-    case 110: return GET_LOOPS_OSX (110);
-    case 111: return GET_LOOPS_OSX (111);
-    case 112: return GET_LOOPS_OSX (112);
-    case 120: return GET_LOOPS_OSX (120);
-    case 121: return GET_LOOPS_OSX (121);
-    case 122: return GET_LOOPS_OSX (122);
-    case 124: return GET_LOOPS_OSX (124);
-    case 130: return GET_LOOPS_OSX (130);
-    case 131: return GET_LOOPS_OSX (131);
-    case 132: return GET_LOOPS_OSX (132);
-    case 133: return GET_LOOPS_OSX (133);
-    case 140: return GET_LOOPS_OSX (140);
-    case 141: return GET_LOOPS_OSX (141);
-    case 150: return GET_LOOPS_OSX (150);
-    case 160: return GET_LOOPS_OSX (160);
-    case 190: return GET_LOOPS_OSX (190);
-    case 200: return GET_LOOPS_OSX (200);
-    case 300: return GET_LOOPS_OSX (300);
-    case 900: return GET_LOOPS_OSX (900);
-    case 1000: return GET_LOOPS_OSX (1000);
-    case 1100: return GET_LOOPS_OSX (1100);
-    case 1400: return GET_LOOPS_OSX (1400);
-    case 1410: return GET_LOOPS_OSX (1410);
-    case 1420: return GET_LOOPS_OSX (1420);
-    case 1421: return GET_LOOPS_OSX (1421);
-    case 1430: return GET_LOOPS_OSX (1430);
-    case 1440: return GET_LOOPS_OSX (1440);
-    case 1441: return GET_LOOPS_OSX (1441);
-    case 1450: return GET_LOOPS_OSX (1450);
-    case 1460: return GET_LOOPS_OSX (1460);
-    case 1700: return GET_LOOPS_OSX (1700);
-    case 1710: return GET_LOOPS_OSX (1710);
-    case 1711: return GET_LOOPS_OSX (1711);
-    case 1720: return GET_LOOPS_OSX (1720);
-    case 1722: return GET_LOOPS_OSX (1722);
-    case 1730: return GET_LOOPS_OSX (1730);
-    case 1731: return GET_LOOPS_OSX (1731);
-    case 1740: return GET_LOOPS_OSX (1740);
-    case 1750: return GET_LOOPS_OSX (1750);
-    case 1760: return GET_LOOPS_OSX (1760);
-    case 2400: return GET_LOOPS_OSX (2400);
-    case 2410: return GET_LOOPS_OSX (2410);
-    case 2600: return GET_LOOPS_OSX (2600);
-    case 2611: return GET_LOOPS_OSX (2611);
-    case 2612: return GET_LOOPS_OSX (2612);
-    case 2711: return GET_LOOPS_OSX (2711);
-    case 2811: return GET_LOOPS_OSX (2811);
-    case 3100: return GET_LOOPS_OSX (3100);
-    case 3200: return GET_LOOPS_OSX (3200);
-    case 3710: return GET_LOOPS_OSX (3710);
-    case 3711: return GET_LOOPS_OSX (3711);
-    case 3800: return GET_LOOPS_OSX (3800);
-    case 4300: return GET_LOOPS_OSX (4300);
-    case 4400: return GET_LOOPS_OSX (4400);
-    case 4500: return GET_LOOPS_OSX (4500);
-    case 4700: return GET_LOOPS_OSX (4700);
-    case 4800: return GET_LOOPS_OSX (4800);
-    case 4900: return GET_LOOPS_OSX (4900);
-    case 5000: return GET_LOOPS_OSX (5000);
-    case 5100: return GET_LOOPS_OSX (5100);
-    case 5300: return GET_LOOPS_OSX (5300);
-    case 5400: return GET_LOOPS_OSX (5400);
-    case 5500: return GET_LOOPS_OSX (5500);
-    case 5600: return GET_LOOPS_OSX (5600);
-    case 5700: return GET_LOOPS_OSX (5700);
-    case 6000: return GET_LOOPS_OSX (6000);
-    case 6100: return GET_LOOPS_OSX (6100);
-    case 6231: return GET_LOOPS_OSX (6231);
-    case 6232: return GET_LOOPS_OSX (6232);
-    case 6233: return GET_LOOPS_OSX (6233);
-    case 6900: return GET_LOOPS_OSX (6900);
-    case 7300: return GET_LOOPS_OSX (7300);
-    case 7500: return GET_LOOPS_OSX (7500);
-    case 7600: return GET_LOOPS_OSX (7600);
-    case 7700: return GET_LOOPS_OSX (7700);
-    case 7800: return GET_LOOPS_OSX (7800);
-    case 8000: return GET_LOOPS_OSX (8000);
-    case 8100: return GET_LOOPS_OSX (8100);
-    case 8200: return GET_LOOPS_OSX (8200);
-    case 8300: return GET_LOOPS_OSX (8300);
-    case 8400: return GET_LOOPS_OSX (8400);
-    case 8500: return GET_LOOPS_OSX (8500);
-    case 8600: return GET_LOOPS_OSX (8600);
-    case 8700: return GET_LOOPS_OSX (8700);
-    case 9700: return GET_LOOPS_OSX (9700);
-    case 9710: return GET_LOOPS_OSX (9710);
-    case 9720: return GET_LOOPS_OSX (9720);
-    case 9800: return GET_LOOPS_OSX (9800);
-    case 9810: return GET_LOOPS_OSX (9810);
-    case 9820: return GET_LOOPS_OSX (9820);
-    case 9900: return GET_LOOPS_OSX (9900);
-    case 10100: return GET_LOOPS_OSX (10100);
-    case 10200: return GET_LOOPS_OSX (10200);
-    case 10400: return GET_LOOPS_OSX (10400);
-    case 10410: return GET_LOOPS_OSX (10410);
-    case 10420: return GET_LOOPS_OSX (10420);
-    case 10600: return GET_LOOPS_OSX (10600);
-    case 10700: return GET_LOOPS_OSX (10700);
-    case 10800: return GET_LOOPS_OSX (10800);
-    case 11000: return GET_LOOPS_OSX (11000);
-    case 11100: return GET_LOOPS_OSX (11100);
-    case 11200: return GET_LOOPS_OSX (11200);
-    case 11300: return GET_LOOPS_OSX (11300);
-    case 11400: return GET_LOOPS_OSX (11400);
-    case 11500: return GET_LOOPS_OSX (11500);
-    case 11700: return GET_LOOPS_OSX (11700);
-    case 11800: return GET_LOOPS_OSX (11800);
-    case 12600: return GET_LOOPS_OSX (12600);
+    if (device_name_nospace[i] == ' ') device_name_nospace[i] = '_';
   }
 
-  return (-1);
-}
+  // find out if there's an alias configured
 
-uint set_kernel_loops (uint hash_mode, bool isGpu)
-{
-  int loops = -1;
-  if (isGpu)
-    loops = set_kernel_loops_osx (hash_mode);
+  tuning_db_alias_t a;
 
-  if (loops != -1)
-    return loops;
+  a.device_name = device_name_nospace;
 
-#else
+  tuning_db_alias_t *alias = bsearch (&a, tuning_db->alias_buf, tuning_db->alias_cnt, sizeof (tuning_db_alias_t), sort_by_tuning_db_alias);
 
-uint set_kernel_loops (uint hash_mode)
-{
+  char *alias_name = (alias == NULL) ? NULL : alias->alias_name;
 
-#endif // OSX
+  // attack-mode 6 and 7 are attack-mode 1 basically
 
-  switch (hash_mode)
+  if (attack_mode == 6) attack_mode = 1;
+  if (attack_mode == 7) attack_mode = 1;
+
+  // bsearch is not ideal but fast enough
+
+  s.device_name = device_name_nospace;
+  s.attack_mode = attack_mode;
+  s.hash_type   = hash_type;
+
+  tuning_db_entry_t *entry = NULL;
+
+  // this will produce all 2^3 combinations required
+
+  for (i = 0; i < 8; i++)
   {
-    case     0: return GET_LOOPS (0);
-    case    10: return GET_LOOPS (10);
-    case    11: return GET_LOOPS (11);
-    case    12: return GET_LOOPS (12);
-    case    20: return GET_LOOPS (20);
-    case    21: return GET_LOOPS (21);
-    case    22: return GET_LOOPS (22);
-    case    23: return GET_LOOPS (23);
-    case    30: return GET_LOOPS (30);
-    case    40: return GET_LOOPS (40);
-    case    50: return GET_LOOPS (50);
-    case    60: return GET_LOOPS (60);
-    case   100: return GET_LOOPS (100);
-    case   101: return GET_LOOPS (101);
-    case   110: return GET_LOOPS (110);
-    case   111: return GET_LOOPS (111);
-    case   112: return GET_LOOPS (112);
-    case   120: return GET_LOOPS (120);
-    case   121: return GET_LOOPS (121);
-    case   122: return GET_LOOPS (122);
-    case   124: return GET_LOOPS (124);
-    case   130: return GET_LOOPS (130);
-    case   131: return GET_LOOPS (131);
-    case   132: return GET_LOOPS (132);
-    case   133: return GET_LOOPS (133);
-    case   140: return GET_LOOPS (140);
-    case   141: return GET_LOOPS (141);
-    case   150: return GET_LOOPS (150);
-    case   160: return GET_LOOPS (160);
-    case   190: return GET_LOOPS (190);
-    case   200: return GET_LOOPS (200);
-    case   300: return GET_LOOPS (300);
-    case   400: return GET_LOOPS (400);
-    case   500: return GET_LOOPS (500);
-    case   501: return GET_LOOPS (501);
-    case   900: return GET_LOOPS (900);
-    case   910: return GET_LOOPS (910);
-    case  1000: return GET_LOOPS (1000);
-    case  1100: return GET_LOOPS (1100);
-    case  1400: return GET_LOOPS (1400);
-    case  1410: return GET_LOOPS (1410);
-    case  1420: return GET_LOOPS (1420);
-    case  1421: return GET_LOOPS (1421);
-    case  1430: return GET_LOOPS (1430);
-    case  1440: return GET_LOOPS (1440);
-    case  1441: return GET_LOOPS (1441);
-    case  1450: return GET_LOOPS (1450);
-    case  1460: return GET_LOOPS (1460);
-    case  1500: return GET_LOOPS (1500);
-    case  1600: return GET_LOOPS (1600);
-    case  1700: return GET_LOOPS (1700);
-    case  1710: return GET_LOOPS (1710);
-    case  1711: return GET_LOOPS (1711);
-    case  1720: return GET_LOOPS (1720);
-    case  1722: return GET_LOOPS (1722);
-    case  1730: return GET_LOOPS (1730);
-    case  1731: return GET_LOOPS (1731);
-    case  1740: return GET_LOOPS (1740);
-    case  1750: return GET_LOOPS (1750);
-    case  1760: return GET_LOOPS (1760);
-    case  1800: return GET_LOOPS (1800);
-    case  2100: return GET_LOOPS (2100);
-    case  2400: return GET_LOOPS (2400);
-    case  2410: return GET_LOOPS (2410);
-    case  2500: return GET_LOOPS (2500);
-    case  2600: return GET_LOOPS (2600);
-    case  2611: return GET_LOOPS (2611);
-    case  2612: return GET_LOOPS (2612);
-    case  2711: return GET_LOOPS (2711);
-    case  2811: return GET_LOOPS (2811);
-    case  3000: return GET_LOOPS (3000);
-    case  3100: return GET_LOOPS (3100);
-    case  3200: return GET_LOOPS (3200);
-    case  3710: return GET_LOOPS (3710);
-    case  3711: return GET_LOOPS (3711);
-    case  3800: return GET_LOOPS (3800);
-    case  4300: return GET_LOOPS (4300);
-    case  4400: return GET_LOOPS (4400);
-    case  4500: return GET_LOOPS (4500);
-    case  4700: return GET_LOOPS (4700);
-    case  4800: return GET_LOOPS (4800);
-    case  4900: return GET_LOOPS (4900);
-    case  5000: return GET_LOOPS (5000);
-    case  5100: return GET_LOOPS (5100);
-    case  5200: return GET_LOOPS (5200);
-    case  5300: return GET_LOOPS (5300);
-    case  5400: return GET_LOOPS (5400);
-    case  5500: return GET_LOOPS (5500);
-    case  5600: return GET_LOOPS (5600);
-    case  5700: return GET_LOOPS (5700);
-    case  5800: return GET_LOOPS (5800);
-    case  6000: return GET_LOOPS (6000);
-    case  6100: return GET_LOOPS (6100);
-    case  6211: return GET_LOOPS (6211);
-    case  6212: return GET_LOOPS (6212);
-    case  6213: return GET_LOOPS (6213);
-    case  6221: return GET_LOOPS (6221);
-    case  6222: return GET_LOOPS (6222);
-    case  6223: return GET_LOOPS (6223);
-    case  6231: return GET_LOOPS (6231);
-    case  6232: return GET_LOOPS (6232);
-    case  6233: return GET_LOOPS (6233);
-    case  6241: return GET_LOOPS (6241);
-    case  6242: return GET_LOOPS (6242);
-    case  6243: return GET_LOOPS (6243);
-    case  6300: return GET_LOOPS (6300);
-    case  6400: return GET_LOOPS (6400);
-    case  6500: return GET_LOOPS (6500);
-    case  6600: return GET_LOOPS (6600);
-    case  6700: return GET_LOOPS (6700);
-    case  6800: return GET_LOOPS (6800);
-    case  6900: return GET_LOOPS (6900);
-    case  7100: return GET_LOOPS (7100);
-    case  7200: return GET_LOOPS (7200);
-    case  7300: return GET_LOOPS (7300);
-    case  7400: return GET_LOOPS (7400);
-    case  7500: return GET_LOOPS (7500);
-    case  7600: return GET_LOOPS (7600);
-    case  7700: return GET_LOOPS (7700);
-    case  7800: return GET_LOOPS (7800);
-    case  7900: return GET_LOOPS (7900);
-    case  8000: return GET_LOOPS (8000);
-    case  8100: return GET_LOOPS (8100);
-    case  8200: return GET_LOOPS (8200);
-    case  8300: return GET_LOOPS (8300);
-    case  8400: return GET_LOOPS (8400);
-    case  8500: return GET_LOOPS (8500);
-    case  8600: return GET_LOOPS (8600);
-    case  8700: return GET_LOOPS (8700);
-    case  8800: return GET_LOOPS (8800);
-    case  8900: return GET_LOOPS (8900);
-    case  9000: return GET_LOOPS (9000);
-    case  9100: return GET_LOOPS (9100);
-    case  9200: return GET_LOOPS (9200);
-    case  9300: return GET_LOOPS (9300);
-    case  9400: return GET_LOOPS (9400);
-    case  9500: return GET_LOOPS (9500);
-    case  9600: return GET_LOOPS (9600);
-    case  9700: return GET_LOOPS (9700);
-    case  9710: return GET_LOOPS (9710);
-    case  9720: return GET_LOOPS (9720);
-    case  9800: return GET_LOOPS (9800);
-    case  9810: return GET_LOOPS (9810);
-    case  9820: return GET_LOOPS (9820);
-    case  9900: return GET_LOOPS (9900);
-    case 10000: return GET_LOOPS (10000);
-    case 10100: return GET_LOOPS (10100);
-    case 10200: return GET_LOOPS (10200);
-    case 10300: return GET_LOOPS (10300);
-    case 10400: return GET_LOOPS (10400);
-    case 10410: return GET_LOOPS (10410);
-    case 10420: return GET_LOOPS (10420);
-    case 10500: return GET_LOOPS (10500);
-    case 10600: return GET_LOOPS (10600);
-    case 10700: return GET_LOOPS (10700);
-    case 10800: return GET_LOOPS (10800);
-    case 10900: return GET_LOOPS (10900);
-    case 11000: return GET_LOOPS (11000);
-    case 11100: return GET_LOOPS (11100);
-    case 11200: return GET_LOOPS (11200);
-    case 11300: return GET_LOOPS (11300);
-    case 11400: return GET_LOOPS (11400);
-    case 11500: return GET_LOOPS (11500);
-    case 11600: return GET_LOOPS (11600);
-    case 11700: return GET_LOOPS (11700);
-    case 11800: return GET_LOOPS (11800);
-    case 11900: return GET_LOOPS (11900);
-    case 12000: return GET_LOOPS (12000);
-    case 12100: return GET_LOOPS (12100);
-    case 12200: return GET_LOOPS (12200);
-    case 12300: return GET_LOOPS (12300);
-    case 12400: return GET_LOOPS (12400);
-    case 12500: return GET_LOOPS (12500);
-    case 12600: return GET_LOOPS (12600);
-    case 12700: return GET_LOOPS (12700);
-    case 12800: return GET_LOOPS (12800);
-    case 12900: return GET_LOOPS (12900);
-    case 13000: return GET_LOOPS (13000);
+    s.device_name = (i & 1) ? "*" : device_name_nospace;
+    s.attack_mode = (i & 2) ?  -1 : attack_mode;
+    s.hash_type   = (i & 4) ?  -1 : hash_type;
+
+    entry = bsearch (&s, tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
+
+    if (entry != NULL) break;
+
+    // in non-wildcard mode do some additional checks:
+
+    if ((i & 1) == 0)
+    {
+      // in case we have an alias-name
+
+      if (alias_name != NULL)
+      {
+        s.device_name = alias_name;
+
+        entry = bsearch (&s, tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
+
+        if (entry != NULL) break;
+      }
+
+      // or by device type
+
+      if (device_param->device_type & CL_DEVICE_TYPE_CPU)
+      {
+        s.device_name = "DEVICE_TYPE_CPU";
+      }
+      else if (device_param->device_type & CL_DEVICE_TYPE_GPU)
+      {
+        s.device_name = "DEVICE_TYPE_GPU";
+      }
+      else if (device_param->device_type & CL_DEVICE_TYPE_ACCELERATOR)
+      {
+        s.device_name = "DEVICE_TYPE_ACCELERATOR";
+      }
+
+      entry = bsearch (&s, tuning_db->entry_buf, tuning_db->entry_cnt, sizeof (tuning_db_entry_t), sort_by_tuning_db_entry);
+
+      if (entry != NULL) break;
+    }
   }
 
-  return 0;
+  // free converted device_name
+
+  myfree (device_name_nospace);
+
+  return entry;
 }
 
 /**
@@ -10030,8 +9880,10 @@ int netscreen_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_len = parse_and_store_salt (salt_buf_ptr, salt_buf, salt_len);
 
-  // max. salt length: salt_buf[32] => 32 - 22 (":Administration Tools:") = 10
-  if (salt_len > 10) return (PARSER_SALT_LENGTH);
+  // max. salt length: 55 (max for MD5) - 22 (":Administration Tools:") - 1 (0x80) = 32
+  // 32 - 4 bytes (to fit w0lr for all attack modes) = 28
+
+  if (salt_len > 28) return (PARSER_SALT_LENGTH);
 
   salt->salt_len = salt_len;
 
@@ -10171,6 +10023,13 @@ int wpa_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   uint salt_len = strlen (in.essid);
 
+  if (salt_len > 36)
+  {
+    log_info ("WARNING: the length of the ESSID is too long. The hccap file may be invalid or corrupted");
+
+    return (PARSER_SALT_LENGTH);
+  }
+
   memcpy (salt->salt_buf, in.essid, salt_len);
 
   salt->salt_len = salt_len;
@@ -10248,8 +10107,15 @@ int wpa_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     }
   }
 
-  salt->salt_buf[10] = digest[1];
-  salt->salt_buf[11] = digest[2];
+  uint32_t *p0 = (uint32_t *) in.essid;
+  uint32_t c0 = 0;
+  uint32_t c1 = 0;
+
+  for (uint i = 0; i < sizeof (in.essid) / sizeof (uint32_t);    i++) c0 ^= *p0++;
+  for (uint i = 0; i < sizeof (wpa->pke) / sizeof (wpa->pke[0]); i++) c1 ^= wpa->pke[i];
+
+  salt->salt_buf[10] = c0;
+  salt->salt_buf[11] = c1;
 
   return (PARSER_OK);
 }
@@ -10406,6 +10272,8 @@ int phpass_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
 int md5crypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 {
+  if (input_len < DISPLAY_LEN_MIN_500) return (PARSER_GLOBAL_LENGTH);
+
   if (memcmp (SIGNATURE_MD5CRYPT, input_buf, 3)) return (PARSER_SIGNATURE_UNMATCHED);
 
   u32 *digest = (u32 *) hash_buf->digest;
@@ -10438,7 +10306,7 @@ int md5crypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     salt->salt_iter = ROUNDS_MD5CRYPT;
   }
 
-  if ((input_len < DISPLAY_LEN_MIN_500) || (input_len > (DISPLAY_LEN_MAX_500 + iterations_len))) return (PARSER_GLOBAL_LENGTH);
+  if (input_len > (DISPLAY_LEN_MAX_500 + iterations_len)) return (PARSER_GLOBAL_LENGTH);
 
   char *hash_pos = strchr (salt_pos, '$');
 
@@ -10927,7 +10795,7 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *hash_pos = strchr (srvchall_pos, ':');
 
-  if (srvchall_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (hash_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
 
   uint srvchall_len = hash_pos - srvchall_pos;
 
@@ -11163,7 +11031,7 @@ int netntlmv2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *hash_pos = strchr (srvchall_pos, ':');
 
-  if (srvchall_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (hash_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
 
   uint srvchall_len = hash_pos - srvchall_pos;
 
@@ -11667,6 +11535,25 @@ int sha1linkedin_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   return (PARSER_OK);
 }
 
+int sha1axcrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if ((input_len < DISPLAY_LEN_MIN_13300) || (input_len > DISPLAY_LEN_MAX_13300)) return (PARSER_GLOBAL_LENGTH);
+
+  if (memcmp (SIGNATURE_AXCRYPT_SHA1, input_buf, 13)) return (PARSER_SIGNATURE_UNMATCHED);
+  u32 *digest = (u32 *) hash_buf->digest;
+
+  input_buf +=14;
+  
+  digest[0] = hex_to_u32 ((const u8 *) &input_buf[ 0]);
+  digest[1] = hex_to_u32 ((const u8 *) &input_buf[ 8]);
+  digest[2] = hex_to_u32 ((const u8 *) &input_buf[16]);
+  digest[3] = hex_to_u32 ((const u8 *) &input_buf[24]);
+  digest[4] = 0x00000000;
+
+  return (PARSER_OK);
+}
+
 int sha1s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 {
   if (data.opts_type & OPTS_TYPE_ST_HEX)
@@ -11754,9 +11641,15 @@ int sha1b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   int tmp_len = base64_decode (base64_to_int, (const u8 *) input_buf + 6, input_len - 6, tmp_buf);
 
+  if (tmp_len < 20) return (PARSER_HASH_LENGTH);
+
   memcpy (digest, tmp_buf, 20);
 
-  salt->salt_len = tmp_len - 20;
+  int salt_len = tmp_len - 20;
+
+  if (salt_len < 0) return (PARSER_SALT_LENGTH);
+
+  salt->salt_len = salt_len;
 
   memcpy (salt->salt_buf, tmp_buf + 20, salt->salt_len);
 
@@ -12302,6 +12195,8 @@ int ikepsk_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   in_off[0] = strtok (input_buf, ":");
 
+  if (in_off[0] == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
   in_len[0] = strlen (in_off[0]);
 
   size_t i;
@@ -12387,6 +12282,8 @@ int ikepsk_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   in_off[0] = strtok (input_buf, ":");
 
+  if (in_off[0] == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
   in_len[0] = strlen (in_off[0]);
 
   size_t i;
@@ -13261,6 +13158,8 @@ int sha512b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   int tmp_len = base64_decode (base64_to_int, (const u8 *) input_buf + 9, input_len - 9, tmp_buf);
 
+  if (tmp_len < 64) return (PARSER_HASH_LENGTH);
+
   memcpy (digest, tmp_buf, 64);
 
   digest[0] = byte_swap_64 (digest[0]);
@@ -13281,7 +13180,11 @@ int sha512b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   digest[6] -= SHA512M_G;
   digest[7] -= SHA512M_H;
 
-  salt->salt_len = tmp_len - 64;
+  int salt_len = tmp_len - 64;
+
+  if (salt_len < 0) return (PARSER_SALT_LENGTH);
+
+  salt->salt_len = salt_len;
 
   memcpy (salt->salt_buf, tmp_buf + 64, salt->salt_len);
 
@@ -14549,6 +14452,8 @@ int peoplesoft_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
+  salt_t *salt = hash_buf->salt;
+
   u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) input_buf, input_len, tmp_buf);
@@ -14567,6 +14472,10 @@ int peoplesoft_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   digest[3] -= SHA1M_D;
   digest[4] -= SHA1M_E;
 
+  salt->salt_buf[0] = 0x80;
+
+  salt->salt_len = 0;
+
   return (PARSER_OK);
 }
 
@@ -18915,6 +18824,180 @@ int rar5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   return (PARSER_OK);
 }
 
+int krb5tgs_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if ((input_len < DISPLAY_LEN_MIN_13100) || (input_len > DISPLAY_LEN_MAX_13100)) return (PARSER_GLOBAL_LENGTH);
+
+  if (memcmp (SIGNATURE_KRB5TGS, input_buf, 11)) return (PARSER_SIGNATURE_UNMATCHED);
+
+  u32 *digest = (u32 *) hash_buf->digest;
+
+  salt_t *salt = hash_buf->salt;
+
+  krb5tgs_t *krb5tgs = (krb5tgs_t *) hash_buf->esalt;
+
+  /**
+   * parse line
+   */
+
+  /* Skip '$' */
+  char *account_pos = input_buf + 11 + 1;
+
+  char *data_pos;
+
+  uint data_len;
+
+  if (account_pos[0] == '*')
+  {
+    account_pos++;
+
+    data_pos = strchr (account_pos, '*');
+
+    /* Skip '*' */
+    data_pos++;
+
+    if (data_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+    uint account_len = data_pos - account_pos + 1;
+
+    if (account_len >= 512) return (PARSER_SALT_LENGTH);
+
+    /* Skip '$' */
+    data_pos++;
+
+    data_len = input_len - 11 - 1 - account_len - 2;
+
+    memcpy (krb5tgs->account_info, account_pos - 1, account_len);
+  }
+  else
+  {
+    /* assume $krb5tgs$23$checksum$edata2 */
+    data_pos = account_pos;
+
+    memcpy (krb5tgs->account_info, "**", 3);
+
+    data_len = input_len - 11 - 1 - 1;
+  }
+
+  if (data_len < ((16 + 32) * 2)) return (PARSER_SALT_LENGTH);
+
+  char *checksum_ptr = (char *) krb5tgs->checksum;
+
+  for (uint i = 0; i < 16 * 2; i += 2)
+  {
+    const char p0 = data_pos[i + 0];
+    const char p1 = data_pos[i + 1];
+
+    *checksum_ptr++ = hex_convert (p1) << 0
+                     | hex_convert (p0) << 4;
+  }
+
+  char *edata_ptr = (char *) krb5tgs->edata2;
+
+  krb5tgs->edata2_len = (data_len - 32) / 2 ;
+
+  /* skip '$' */
+  for (uint i = 16 * 2 + 1; i < (krb5tgs->edata2_len * 2) + (16 * 2 + 1); i += 2)
+  {
+    const char p0 = data_pos[i + 0];
+    const char p1 = data_pos[i + 1];
+    *edata_ptr++ = hex_convert (p1) << 0
+                    | hex_convert (p0) << 4;
+  }
+
+ /* this is needed for hmac_md5 */
+  *edata_ptr++ = 0x80;
+
+  salt->salt_buf[0] = krb5tgs->checksum[0];
+  salt->salt_buf[1] = krb5tgs->checksum[1];
+  salt->salt_buf[2] = krb5tgs->checksum[2];
+  salt->salt_buf[3] = krb5tgs->checksum[3];
+
+  salt->salt_len = 32;
+
+  digest[0] = krb5tgs->checksum[0];
+  digest[1] = krb5tgs->checksum[1];
+  digest[2] = krb5tgs->checksum[2];
+  digest[3] = krb5tgs->checksum[3];
+
+  return (PARSER_OK);
+}
+
+int axcrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if ((input_len < DISPLAY_LEN_MIN_13200) || (input_len > DISPLAY_LEN_MAX_13200)) return (PARSER_GLOBAL_LENGTH);
+
+  if (memcmp (SIGNATURE_AXCRYPT, input_buf, 11)) return (PARSER_SIGNATURE_UNMATCHED);
+
+  u32 *digest = (u32 *) hash_buf->digest;
+
+  salt_t *salt = hash_buf->salt;
+
+  /**
+   * parse line
+   */
+
+  /* Skip '*' */
+  char *wrapping_rounds_pos = input_buf + 11 + 1;
+
+  char *salt_pos;
+
+  char *wrapped_key_pos;
+  
+  char *data_pos;
+
+  salt->salt_iter = atoi (wrapping_rounds_pos);
+  
+  salt_pos = strchr (wrapping_rounds_pos, '*');
+
+  if (salt_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  
+  uint wrapping_rounds_len = salt_pos - wrapping_rounds_pos;
+
+  /* Skip '*' */
+  salt_pos++;
+  
+  data_pos = salt_pos;
+  
+  wrapped_key_pos = strchr (salt_pos, '*');
+
+  if (wrapped_key_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+  uint salt_len = wrapped_key_pos - salt_pos;
+
+  if (salt_len != 32) return (PARSER_SALT_LENGTH);
+
+  /* Skip '*' */
+  wrapped_key_pos++;
+
+  uint wrapped_key_len = input_len - 11 - 1 - wrapping_rounds_len - 1 - salt_len - 1;
+
+  if (wrapped_key_len != 48) return (PARSER_SALT_LENGTH);
+
+  salt->salt_buf[0] = hex_to_u32 ((const u8 *) &data_pos[ 0]);
+  salt->salt_buf[1] = hex_to_u32 ((const u8 *) &data_pos[ 8]);
+  salt->salt_buf[2] = hex_to_u32 ((const u8 *) &data_pos[16]);
+  salt->salt_buf[3] = hex_to_u32 ((const u8 *) &data_pos[24]);
+
+  data_pos += 33;
+
+  salt->salt_buf[4] = hex_to_u32 ((const u8 *) &data_pos[ 0]);
+  salt->salt_buf[5] = hex_to_u32 ((const u8 *) &data_pos[ 8]);
+  salt->salt_buf[6] = hex_to_u32 ((const u8 *) &data_pos[16]); 
+  salt->salt_buf[7] = hex_to_u32 ((const u8 *) &data_pos[24]);
+  salt->salt_buf[8] = hex_to_u32 ((const u8 *) &data_pos[32]);
+  salt->salt_buf[9] = hex_to_u32 ((const u8 *) &data_pos[40]);
+
+  salt->salt_len = 40;
+
+  digest[0] = salt->salt_buf[0];
+  digest[1] = salt->salt_buf[1];
+  digest[2] = salt->salt_buf[2];
+  digest[3] = salt->salt_buf[3];
+
+  return (PARSER_OK);
+}
+
 int cf10_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 {
   if ((input_len < DISPLAY_LEN_MIN_12600) || (input_len > DISPLAY_LEN_MAX_12600)) return (PARSER_GLOBAL_LENGTH);