Removed SHA1 optimization.
[hashcat.git] / src / shared.c
index d08c2ba..13ed50e 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
  */
  * 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)));
@@ -3087,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
@@ -3156,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
@@ -4191,13 +4197,13 @@ uint count_lines (FILE *fd)
 {
   uint cnt = 0;
 
-  char *buf = (char *) mymalloc (BUFSIZ + 1);
+  char *buf = (char *) mymalloc (HCBUFSIZ + 1);
 
   char prev = '\n';
 
   while (!feof (fd))
   {
-    size_t nread = fread (buf, sizeof (char), BUFSIZ, fd);
+    size_t nread = fread (buf, sizeof (char), HCBUFSIZ, fd);
 
     if (nread < 1) continue;
 
@@ -4348,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;
@@ -5439,7 +5453,7 @@ int fgetl (FILE *fp, char *line_buf)
 
     line_len++;
 
-    if (line_len == BUFSIZ) line_len--;
+    if (line_len == HCBUFSIZ) line_len--;
 
     if (c == '\n') break;
   }
@@ -5677,6 +5691,7 @@ char *strhashtype (const uint hash_mode)
     case   121: return ((char *) HT_00121); break;
     case   122: return ((char *) HT_00122); break;
     case   124: return ((char *) HT_00124); break;
+    case   125: return ((char *) HT_00125); break;
     case   130: return ((char *) HT_00130); break;
     case   131: return ((char *) HT_00131); break;
     case   132: return ((char *) HT_00132); break;
@@ -5835,6 +5850,10 @@ char *strhashtype (const uint hash_mode)
     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;
+    case 13400: return ((char *) HT_13400); break;
+    case 13500: return ((char *) HT_13500); break;
   }
 
   return ((char *) "Unknown");
@@ -5860,7 +5879,7 @@ char *strstatus (const uint devices_status)
   return ((char *) "Unknown");
 }
 
-void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
+void ascii_digest (char *out_buf, uint salt_pos, uint digest_pos)
 {
   uint hash_type = data.hash_type;
   uint hash_mode = data.hash_mode;
@@ -6168,7 +6187,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 23)
   {
-    // do not show the \nskyper\n part in output
+    // do not show the skyper part in output
 
     char *salt_buf_ptr = (char *) salt.salt_buf;
 
@@ -6214,7 +6233,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     snprintf (out_buf, len-1, "{SSHA}%s", ptr_plain);
   }
-  else if (hash_mode == 122)
+  else if ((hash_mode == 122) || (hash_mode == 125))
   {
     snprintf (out_buf, len-1, "%s%08x%08x%08x%08x%08x",
       (char *) salt.salt_buf,
@@ -6563,35 +6582,20 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     wpa_t *wpa = &wpas[salt_pos];
 
-    uint pke[25] = { 0 };
-
-    char *pke_ptr = (char *) pke;
-
-    for (uint i = 0; i < 25; i++)
-    {
-      pke[i] = byte_swap_32 (wpa->pke[i]);
-    }
-
-    unsigned char mac1[6] = { 0 };
-    unsigned char mac2[6] = { 0 };
-
-    memcpy (mac1, pke_ptr + 23, 6);
-    memcpy (mac2, pke_ptr + 29, 6);
-
     snprintf (out_buf, len-1, "%s:%02x%02x%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x",
       (char *) salt.salt_buf,
-      mac1[0],
-      mac1[1],
-      mac1[2],
-      mac1[3],
-      mac1[4],
-      mac1[5],
-      mac2[0],
-      mac2[1],
-      mac2[2],
-      mac2[3],
-      mac2[4],
-      mac2[5]);
+      wpa->orig_mac1[0],
+      wpa->orig_mac1[1],
+      wpa->orig_mac1[2],
+      wpa->orig_mac1[3],
+      wpa->orig_mac1[4],
+      wpa->orig_mac1[5],
+      wpa->orig_mac2[0],
+      wpa->orig_mac2[1],
+      wpa->orig_mac2[2],
+      wpa->orig_mac2[3],
+      wpa->orig_mac2[4],
+      wpa->orig_mac2[5]);
   }
   else if (hash_mode == 4400)
   {
@@ -7220,6 +7224,12 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   {
     char digest_buf_c[34] = { 0 };
 
+    digest_buf[0] = byte_swap_32 (digest_buf[0]);
+    digest_buf[1] = byte_swap_32 (digest_buf[1]);
+    digest_buf[2] = byte_swap_32 (digest_buf[2]);
+    digest_buf[3] = byte_swap_32 (digest_buf[3]);
+    digest_buf[4] = byte_swap_32 (digest_buf[4]);
+
     base32_encode (int_to_itoa32, (const u8 *) digest_buf, 20, (u8 *) digest_buf_c);
 
     digest_buf_c[32] = 0;
@@ -8288,7 +8298,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     u8 *ptr_checksum  = (u8 *) krb5tgs->checksum;
     u8 *ptr_edata2 = (u8 *) krb5tgs->edata2;
 
-    char data[256] = { 0 };
+    char data[2560 * 4 * 2] = { 0 };
 
     char *ptr_data = data;
 
@@ -8298,17 +8308,203 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     /* skip '$' */
     ptr_data++;
 
-    for (uint i = 0; i < 32; i++, ptr_data += 2)
+    for (uint i = 0; i < krb5tgs->edata2_len; i++, ptr_data += 2)
       sprintf (ptr_data, "%02x", ptr_edata2[i]);
 
-    *ptr_data = 0;
-
     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_mode == 13400)
+  {
+    keepass_t *keepasss = (keepass_t *) data.esalts_buf;
+
+    keepass_t *keepass = &keepasss[salt_pos];
+
+    u32 version     = (u32) keepass->version;
+    u32 rounds      = salt.salt_iter;
+    u32 algorithm   = (u32) keepass->algorithm;
+    u32 keyfile_len = (u32) keepass->keyfile_len;
+
+    u32 *ptr_final_random_seed  = (u32 *) keepass->final_random_seed ;
+    u32 *ptr_transf_random_seed = (u32 *) keepass->transf_random_seed ;
+    u32 *ptr_enc_iv             = (u32 *) keepass->enc_iv ;
+    u32 *ptr_contents_hash      = (u32 *) keepass->contents_hash ;
+    u32 *ptr_keyfile            = (u32 *) keepass->keyfile ;
+
+    /* specific to version 1 */
+    u32 contents_len;
+    u32 *ptr_contents;
+
+    /* specific to version 2 */
+    u32 expected_bytes_len;
+    u32 *ptr_expected_bytes;
+
+    u32 final_random_seed_len;
+    u32 transf_random_seed_len;
+    u32 enc_iv_len;
+    u32 contents_hash_len;
+
+    transf_random_seed_len = 8;
+    enc_iv_len             = 4;
+    contents_hash_len      = 8;
+    final_random_seed_len  = 8;
+
+    if (version == 1)
+      final_random_seed_len = 4;
+
+    snprintf (out_buf, len-1, "%s*%d*%d*%d",
+      SIGNATURE_KEEPASS,
+      version,
+      rounds,
+      algorithm);
+
+    char *ptr_data = out_buf;
+
+    ptr_data += strlen(out_buf);
+
+    *ptr_data = '*';
+    ptr_data++;
+
+    for (uint i = 0; i < final_random_seed_len; i++, ptr_data += 8)
+      sprintf (ptr_data, "%08x", ptr_final_random_seed[i]);
+
+    *ptr_data = '*';
+    ptr_data++;
+
+    for (uint i = 0; i < transf_random_seed_len; i++, ptr_data += 8)
+      sprintf (ptr_data, "%08x", ptr_transf_random_seed[i]);
+
+    *ptr_data = '*';
+    ptr_data++;
+
+    for (uint i = 0; i < enc_iv_len; i++, ptr_data += 8)
+      sprintf (ptr_data, "%08x", ptr_enc_iv[i]);
+
+    *ptr_data = '*';
+    ptr_data++;
+
+    if (version == 1)
+    {
+      contents_len = (u32)   keepass->contents_len;
+      ptr_contents = (u32 *) keepass->contents;
+
+      for (uint i = 0; i < contents_hash_len; i++, ptr_data += 8)
+        sprintf (ptr_data, "%08x", ptr_contents_hash[i]);
+
+      *ptr_data = '*';
+      ptr_data++;
+
+      /* inline flag */
+      *ptr_data = '1';
+      ptr_data++;
+
+      *ptr_data = '*';
+      ptr_data++;
+
+      char ptr_contents_len[10] = { 0 };
+
+      sprintf ((char*) ptr_contents_len, "%d", contents_len);
+
+      sprintf (ptr_data, "%d", contents_len);
+
+      ptr_data += strlen(ptr_contents_len);
+
+      *ptr_data = '*';
+      ptr_data++;
+
+      for (uint i = 0; i < contents_len / 4; i++, ptr_data += 8)
+        sprintf (ptr_data, "%08x", ptr_contents[i]);
+    }
+    else if (version == 2)
+    {
+      expected_bytes_len = 8;
+      ptr_expected_bytes = (u32 *) keepass->expected_bytes ;
+
+      for (uint i = 0; i < expected_bytes_len; i++, ptr_data += 8)
+        sprintf (ptr_data, "%08x", ptr_expected_bytes[i]);
+
+      *ptr_data = '*';
+      ptr_data++;
+
+      for (uint i = 0; i < contents_hash_len; i++, ptr_data += 8)
+        sprintf (ptr_data, "%08x", ptr_contents_hash[i]);
+    }
+    if (keyfile_len)
+    {
+      *ptr_data = '*';
+      ptr_data++;
+
+      /* inline flag */
+      *ptr_data = '1';
+      ptr_data++;
+
+      *ptr_data = '*';
+      ptr_data++;
+
+      sprintf (ptr_data, "%d", keyfile_len);
+
+      ptr_data += 2;
+
+      *ptr_data = '*';
+      ptr_data++;
+
+      for (uint i = 0; i < 8; i++, ptr_data += 8)
+        sprintf (ptr_data, "%08x", ptr_keyfile[i]);
+    }
+  }
+  else if (hash_mode == 13500)
+  {
+    pstoken_t *pstokens = (pstoken_t *) data.esalts_buf;
+    pstoken_t *pstoken  = &pstokens[salt_pos];
+
+    uint mysalt = pstoken->salt_len > 512 ? 512 : pstoken->salt_len;
+
+    char pstoken_tmp[1024 + 1];
+    u8 *salt_buf_ptr = (u8 *) pstoken->salt_buf;
+
+    memset(pstoken_tmp, 0, sizeof (pstoken_tmp));
+
+    for (uint i = 0; i < mysalt; i++)
+    {
+      snprintf(&pstoken_tmp[i*2], 2, "%02x", salt_buf_ptr[i]);
+    }
+
+    snprintf (out_buf, len-1, "%08x%08x%08x%08x%08x:%s",
+        digest_buf[0],
+        digest_buf[1],
+        digest_buf[2],
+        digest_buf[3],
+        digest_buf[4],
+       pstoken_tmp);
+  }
   else
   {
     if (hash_type == HASH_TYPE_MD4)
@@ -8602,19 +8798,10 @@ void to_hccap_t (hccap_t *hccap, uint salt_pos, uint digest_pos)
     memcpy (hccap->eapol, wpa->eapol, wpa->eapol_size);
   }
 
-  uint pke_tmp[25] = { 0 };
-
-  for (int i = 5; i < 25; i++)
-  {
-    pke_tmp[i] = byte_swap_32 (wpa->pke[i]);
-  }
-
-  char *pke_ptr = (char *) pke_tmp;
-
-  memcpy (hccap->mac1,   pke_ptr + 23,  6);
-  memcpy (hccap->mac2,   pke_ptr + 29,  6);
-  memcpy (hccap->nonce1, pke_ptr + 67, 32);
-  memcpy (hccap->nonce2, pke_ptr + 35, 32);
+  memcpy (hccap->mac1,   wpa->orig_mac1,    6);
+  memcpy (hccap->mac2,   wpa->orig_mac2,    6);
+  memcpy (hccap->nonce1, wpa->orig_nonce1, 32);
+  memcpy (hccap->nonce2, wpa->orig_nonce2, 32);
 
   char *digests_buf_ptr = (char *) data.digests_buf;
 
@@ -8817,18 +9004,18 @@ restore_data_t *init_restore (int argc, char **argv)
 
       if (rd->pid)
       {
-        char pidbin[BUFSIZ] = { 0 };
+        char *pidbin = (char *) mymalloc (HCBUFSIZ);
 
         int pidbin_len = -1;
 
         #ifdef _POSIX
-        snprintf (pidbin, sizeof (pidbin) - 1, "/proc/%d/cmdline", rd->pid);
+        snprintf (pidbin, HCBUFSIZ - 1, "/proc/%d/cmdline", rd->pid);
 
         FILE *fd = fopen (pidbin, "rb");
 
         if (fd)
         {
-          pidbin_len = fread (pidbin, 1, BUFSIZ, fd);
+          pidbin_len = fread (pidbin, 1, HCBUFSIZ, fd);
 
           pidbin[pidbin_len] = 0;
 
@@ -8853,12 +9040,12 @@ restore_data_t *init_restore (int argc, char **argv)
         #elif _WIN
         HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, rd->pid);
 
-        char pidbin2[BUFSIZ] = { 0 };
+        char *pidbin2 = (char *) mymalloc (HCBUFSIZ);
 
         int pidbin2_len = -1;
 
-        pidbin_len = GetModuleFileName (NULL, pidbin, BUFSIZ);
-        pidbin2_len = GetModuleFileNameEx (hProcess, NULL, pidbin2, BUFSIZ);
+        pidbin_len = GetModuleFileName (NULL, pidbin, HCBUFSIZ);
+        pidbin2_len = GetModuleFileNameEx (hProcess, NULL, pidbin2, HCBUFSIZ);
 
         pidbin[pidbin_len] = 0;
         pidbin2[pidbin2_len] = 0;
@@ -8872,7 +9059,12 @@ restore_data_t *init_restore (int argc, char **argv)
             exit (-1);
           }
         }
+
+        myfree (pidbin2);
+
         #endif
+
+        myfree (pidbin);
       }
 
       if (rd->version_bin < RESTORE_MIN)
@@ -8927,11 +9119,11 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
 
   rd->argv = (char **) mycalloc (rd->argc, sizeof (char *));
 
+  char *buf = (char *) mymalloc (HCBUFSIZ);
+
   for (uint i = 0; i < rd->argc; i++)
   {
-    char buf[BUFSIZ] = { 0 };
-
-    if (fgets (buf, BUFSIZ - 1, fp) == NULL)
+    if (fgets (buf, HCBUFSIZ - 1, fp) == NULL)
     {
       log_error ("ERROR: cannot read %s", eff_restore_file);
 
@@ -8945,32 +9137,18 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
     rd->argv[i] = mystrdup (buf);
   }
 
-  fclose (fp);
-
-  char new_cwd[1024] = { 0 };
-
-  char *nwd = getcwd (new_cwd, sizeof (new_cwd));
-
-  if (nwd == NULL)
-  {
-    log_error ("Restore file is corrupted");
-  }
-
-  if (strncmp (new_cwd, rd->cwd, sizeof (new_cwd)) != 0)
-  {
-    if (getcwd (rd->cwd, sizeof (rd->cwd)) == NULL)
-    {
-      log_error ("ERROR: could not determine current user path: %s", strerror (errno));
+  myfree (buf);
 
-      exit (-1);
-    }
+  fclose (fp);
 
-    log_info ("WARNING: Found old restore file, updating path to %s...", new_cwd);
-  }
+  log_info ("INFO: Changing current working directory to the path found within the .restore file: '%s'", rd->cwd);
 
   if (chdir (rd->cwd))
   {
-    log_error ("ERROR: cannot chdir to %s: %s", rd->cwd, strerror (errno));
+    log_error ("ERROR: The directory '%s' does not exist. It is needed to restore (--restore) the session.\n"
+               "       You could either create this directory (or link it) or update the .restore file using e.g. the analyze_hc_restore.pl tool:\n"
+               "       https://github.com/philsmd/analyze_hc_restore\n"
+               "       The directory must be relative to (or contain) all files/folders mentioned within the command line.", rd->cwd);
 
     exit (-1);
   }
@@ -9141,11 +9319,11 @@ tuning_db_t *tuning_db_init (const char *tuning_db_file)
 
   int line_num = 0;
 
+  char *buf = (char *) mymalloc (HCBUFSIZ);
+
   while (!feof (fp))
   {
-    char buf[BUFSIZ];
-
-    char *line_buf = fgets (buf, sizeof (buf) - 1, fp);
+    char *line_buf = fgets (buf, HCBUFSIZ - 1, fp);
 
     if (line_buf == NULL) break;
 
@@ -9274,6 +9452,8 @@ tuning_db_t *tuning_db_init (const char *tuning_db_file)
     }
   }
 
+  myfree (buf);
+
   fclose (fp);
 
   // todo: print loaded 'cnt' message
@@ -9286,13 +9466,13 @@ tuning_db_t *tuning_db_init (const char *tuning_db_file)
   return tuning_db;
 }
 
-tuning_db_entry_t *tuning_db_search (tuning_db_t *tuning_db, char *device_name, int attack_mode, int hash_type)
+tuning_db_entry_t *tuning_db_search (tuning_db_t *tuning_db, hc_device_param_t *device_param, int attack_mode, int hash_type)
 {
   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_name);
+  char *device_name_nospace = strdup (device_param->device_name);
 
   int device_name_length = strlen (device_name_nospace);
 
@@ -9338,11 +9518,35 @@ tuning_db_entry_t *tuning_db_search (tuning_db_t *tuning_db, char *device_name,
 
     if (entry != NULL) break;
 
-    // in non-wildcard mode also check the alias_name
+    // in non-wildcard mode do some additional checks:
 
-    if (((i & 1) == 0) && (alias_name != NULL))
+    if ((i & 1) == 0)
     {
-      s.device_name = alias_name;
+      // 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);
 
@@ -9592,6 +9796,43 @@ int lm_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   return (PARSER_OK);
 }
 
+int arubaos_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if ((input_len < DISPLAY_LEN_MIN_125) || (input_len > DISPLAY_LEN_MAX_125)) return (PARSER_GLOBAL_LENGTH);
+
+  if ((input_buf[8] != '0') || (input_buf[9] != '1')) return (PARSER_SIGNATURE_UNMATCHED);
+
+  u32 *digest = (u32 *) hash_buf->digest;
+
+  salt_t *salt = hash_buf->salt;
+
+  char *hash_pos = input_buf + 10;
+
+  digest[0] = hex_to_u32 ((const u8 *) &hash_pos[ 0]);
+  digest[1] = hex_to_u32 ((const u8 *) &hash_pos[ 8]);
+  digest[2] = hex_to_u32 ((const u8 *) &hash_pos[16]);
+  digest[3] = hex_to_u32 ((const u8 *) &hash_pos[24]);
+  digest[4] = hex_to_u32 ((const u8 *) &hash_pos[32]);
+
+  digest[0] -= SHA1M_A;
+  digest[1] -= SHA1M_B;
+  digest[2] -= SHA1M_C;
+  digest[3] -= SHA1M_D;
+  digest[4] -= SHA1M_E;
+
+  uint salt_len = 10;
+
+  char *salt_buf_ptr = (char *) salt->salt_buf;
+
+  salt_len = parse_and_store_salt (salt_buf_ptr, input_buf, salt_len);
+
+  if (salt_len == UINT_MAX) return (PARSER_SALT_LENGTH);
+
+  salt->salt_len = salt_len;
+
+  return (PARSER_OK);
+}
+
 int osx1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 {
   if ((input_len < DISPLAY_LEN_MIN_122) || (input_len > DISPLAY_LEN_MAX_122)) return (PARSER_GLOBAL_LENGTH);
@@ -9817,8 +10058,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;
 
@@ -9958,6 +10201,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;
@@ -9995,6 +10245,11 @@ int wpa_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     wpa->pke[i] = byte_swap_32 (wpa->pke[i]);
   }
 
+  memcpy (wpa->orig_mac1,   in.mac1,   6);
+  memcpy (wpa->orig_mac2,   in.mac2,   6);
+  memcpy (wpa->orig_nonce1, in.nonce1, 32);
+  memcpy (wpa->orig_nonce2, in.nonce2, 32);
+
   wpa->keyver = in.keyver;
 
   if (wpa->keyver > 255)
@@ -10035,8 +10290,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);
 }
@@ -10193,6 +10455,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;
@@ -10225,7 +10489,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, '$');
 
@@ -10714,7 +10978,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;
 
@@ -10950,7 +11214,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;
 
@@ -11454,6 +11718,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)
@@ -11498,6 +11781,54 @@ int sha1s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   return (PARSER_OK);
 }
 
+int pstoken_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if (data.opts_type & OPTS_TYPE_ST_HEX)
+  {
+    if ((input_len < DISPLAY_LEN_MIN_13500) || (input_len > DISPLAY_LEN_MAX_13500)) return (PARSER_GLOBAL_LENGTH);
+  }
+  else
+  {
+    if ((input_len < DISPLAY_LEN_MIN_13500) || (input_len > DISPLAY_LEN_MAX_13500)) return (PARSER_GLOBAL_LENGTH);
+  }
+
+  u32 *digest = (u32 *) hash_buf->digest;
+  salt_t *salt = hash_buf->salt;
+  pstoken_t *pstoken = (pstoken_t *) hash_buf->esalt;
+  u8 pstoken_tmp[DISPLAY_LEN_MAX_13500 - 40 - 1];
+
+  memset(pstoken_tmp, 0, DISPLAY_LEN_MAX_13500 - 40 - 1);
+
+  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] = hex_to_u32 ((const u8 *) &input_buf[32]);
+
+  if (input_buf[40] != data.separator) return (PARSER_SEPARATOR_UNMATCHED);
+
+  uint salt_len = input_len - 40 - 1;
+
+  char *salt_buf = input_buf + 40 + 1;
+
+  if (salt_len == UINT_MAX || salt_len % 2 != 0) return (PARSER_SALT_LENGTH);
+
+  for (uint i = 0; i < salt_len / 2; i++) 
+  { 
+    pstoken_tmp[i] = hex_to_u8 ((const u8 *) &salt_buf[i * 2]); 
+  }
+
+  salt_len /= 2;
+  salt->salt_len = salt_len;
+  pstoken->salt_len = salt_len;
+
+  memcpy(salt->salt_buf, pstoken_tmp, 16);
+  memcpy(pstoken->salt_buf, pstoken_tmp, salt_len);
+
+  return (PARSER_OK);
+}
+
+
 int sha1b64_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 {
   if ((input_len < DISPLAY_LEN_MIN_101) || (input_len > DISPLAY_LEN_MAX_101)) return (PARSER_GLOBAL_LENGTH);
@@ -11541,9 +11872,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);
 
@@ -12089,6 +12426,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;
@@ -12174,6 +12513,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;
@@ -13048,6 +13389,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]);
@@ -13068,7 +13411,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);
 
@@ -14336,6 +14683,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);
@@ -14354,6 +14703,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);
 }
 
@@ -14557,9 +14910,13 @@ int scrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode
 
+  int salt_len_base64 = hash_pos - saltbuf_pos;
+
+  if (salt_len_base64 > 45) return (PARSER_SALT_LENGTH);
+
   u8 tmp_buf[33] = { 0 };
 
-  int tmp_len = base64_decode (base64_to_int, (const u8 *) saltbuf_pos, hash_pos - saltbuf_pos, tmp_buf);
+  int tmp_len = base64_decode (base64_to_int, (const u8 *) saltbuf_pos, salt_len_base64, tmp_buf);
 
   char *salt_buf_ptr = (char *) salt->salt_buf;
 
@@ -15932,16 +16289,18 @@ int crammd5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *hash_pos = strchr (salt_pos, '$');
 
-  uint salt_len = hash_pos - salt_pos;
-
   if (hash_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
 
+  uint salt_len = hash_pos - salt_pos;
+
   hash_pos++;
 
   uint hash_len = input_len - 10 - salt_len - 1;
 
   // base64 decode salt
 
+  if (salt_len > 133) return (PARSER_SALT_LENGTH);
+
   u8 tmp_buf[100] = { 0 };
 
   salt_len = base64_decode (base64_to_int, (const u8 *) salt_pos, salt_len, tmp_buf);
@@ -15954,12 +16313,16 @@ int crammd5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  // base64 decode salt
+  // base64 decode hash
+
+  if (hash_len > 133) return (PARSER_HASH_LENGTH);
 
   memset (tmp_buf, 0, sizeof (tmp_buf));
 
   hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_len, tmp_buf);
 
+  if (hash_len < 32 + 1) return (PARSER_SALT_LENGTH);
+
   uint user_len = hash_len - 32;
 
   const u8 *tmp_hash = tmp_buf + user_len;
@@ -18719,8 +19082,8 @@ int krb5tgs_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
    */
 
   /* Skip '$' */
-  char *account_pos = input_buf + 11 + 1; 
-  
+  char *account_pos = input_buf + 11 + 1;
+
   char *data_pos;
 
   uint data_len;
@@ -18772,22 +19135,25 @@ int krb5tgs_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *edata_ptr = (char *) krb5tgs->edata2;
 
+  krb5tgs->edata2_len = (data_len - 32) / 2 ;
+
   /* skip '$' */
-  for (uint i = 16 * 2 + 1; i < input_len; i += 2)
+  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;
   }
-  
-  krb5tgs->edata2_len = strlen (edata_ptr - input_len) / (2 * 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];
@@ -18798,6 +19164,383 @@ int krb5tgs_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   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 keepass_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
+{
+  if ((input_len < DISPLAY_LEN_MIN_13400) || (input_len > DISPLAY_LEN_MAX_13400)) return (PARSER_GLOBAL_LENGTH);
+
+  if (memcmp (SIGNATURE_KEEPASS, input_buf, 9)) return (PARSER_SIGNATURE_UNMATCHED);
+
+  u32 *digest = (u32 *) hash_buf->digest;
+
+  salt_t *salt = hash_buf->salt;
+
+  keepass_t *keepass = (keepass_t *) hash_buf->esalt;
+
+  /**
+   * parse line
+   */
+
+  char *version_pos;
+
+  char *rounds_pos;
+
+  char *algorithm_pos;
+
+  char *final_random_seed_pos;
+  u32   final_random_seed_len;
+
+  char *transf_random_seed_pos;
+  u32   transf_random_seed_len;
+
+  char *enc_iv_pos;
+  u32   enc_iv_len;
+
+   /* default is no keyfile provided */
+   char *keyfile_len_pos;
+   u32   keyfile_len = 0;
+   u32   is_keyfile_present = 0;
+   char *keyfile_inline_pos;
+   char *keyfile_pos;
+
+  /* specific to version 1 */
+  char *contents_len_pos;
+  u32   contents_len;
+  char *contents_pos;
+
+  /* specific to version 2 */
+  char *expected_bytes_pos;
+  u32   expected_bytes_len;
+
+  char *contents_hash_pos;
+  u32   contents_hash_len;
+
+  version_pos = input_buf + 8 + 1 + 1;
+
+  keepass->version = atoi (version_pos);
+
+  rounds_pos = strchr (version_pos, '*');
+
+  if (rounds_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+  rounds_pos++;
+
+  salt->salt_iter = (atoi (rounds_pos));
+
+  algorithm_pos = strchr (rounds_pos, '*');
+
+  if (algorithm_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+  algorithm_pos++;
+
+  keepass->algorithm = atoi (algorithm_pos);
+
+  final_random_seed_pos = strchr (algorithm_pos, '*');
+
+  if (final_random_seed_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+  final_random_seed_pos++;
+
+  keepass->final_random_seed[0] = hex_to_u32 ((const u8 *) &final_random_seed_pos[ 0]);
+  keepass->final_random_seed[1] = hex_to_u32 ((const u8 *) &final_random_seed_pos[ 8]);
+  keepass->final_random_seed[2] = hex_to_u32 ((const u8 *) &final_random_seed_pos[16]);
+  keepass->final_random_seed[3] = hex_to_u32 ((const u8 *) &final_random_seed_pos[24]);
+
+  if (keepass->version == 2)
+  {
+    keepass->final_random_seed[4] = hex_to_u32 ((const u8 *) &final_random_seed_pos[32]);
+    keepass->final_random_seed[5] = hex_to_u32 ((const u8 *) &final_random_seed_pos[40]);
+    keepass->final_random_seed[6] = hex_to_u32 ((const u8 *) &final_random_seed_pos[48]);
+    keepass->final_random_seed[7] = hex_to_u32 ((const u8 *) &final_random_seed_pos[56]);
+  }
+
+  transf_random_seed_pos = strchr (final_random_seed_pos, '*');
+
+  if (transf_random_seed_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+  final_random_seed_len = transf_random_seed_pos - final_random_seed_pos;
+
+  if (keepass->version == 1 && final_random_seed_len != 32) return (PARSER_SALT_LENGTH);
+  if (keepass->version == 2 && final_random_seed_len != 64) return (PARSER_SALT_LENGTH);
+
+  transf_random_seed_pos++;
+
+  keepass->transf_random_seed[0] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[ 0]);
+  keepass->transf_random_seed[1] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[ 8]);
+  keepass->transf_random_seed[2] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[16]);
+  keepass->transf_random_seed[3] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[24]);
+  keepass->transf_random_seed[4] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[32]);
+  keepass->transf_random_seed[5] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[40]);
+  keepass->transf_random_seed[6] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[48]);
+  keepass->transf_random_seed[7] = hex_to_u32 ((const u8 *) &transf_random_seed_pos[56]);
+
+  enc_iv_pos = strchr (transf_random_seed_pos, '*');
+
+  if (enc_iv_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+  transf_random_seed_len = enc_iv_pos - transf_random_seed_pos;
+
+  if (transf_random_seed_len != 64) return (PARSER_SALT_LENGTH);
+
+  enc_iv_pos++;
+
+  keepass->enc_iv[0] = hex_to_u32 ((const u8 *) &enc_iv_pos[ 0]);
+  keepass->enc_iv[1] = hex_to_u32 ((const u8 *) &enc_iv_pos[ 8]);
+  keepass->enc_iv[2] = hex_to_u32 ((const u8 *) &enc_iv_pos[16]);
+  keepass->enc_iv[3] = hex_to_u32 ((const u8 *) &enc_iv_pos[24]);
+
+  if (keepass->version == 1)
+  {
+    contents_hash_pos = strchr (enc_iv_pos, '*');
+
+    if (contents_hash_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+    enc_iv_len = contents_hash_pos - enc_iv_pos;
+
+    if (enc_iv_len != 32) return (PARSER_SALT_LENGTH);
+
+    contents_hash_pos++;
+
+    keepass->contents_hash[0] = hex_to_u32 ((const u8 *) &contents_hash_pos[ 0]);
+    keepass->contents_hash[1] = hex_to_u32 ((const u8 *) &contents_hash_pos[ 8]);
+    keepass->contents_hash[2] = hex_to_u32 ((const u8 *) &contents_hash_pos[16]);
+    keepass->contents_hash[3] = hex_to_u32 ((const u8 *) &contents_hash_pos[24]);
+    keepass->contents_hash[4] = hex_to_u32 ((const u8 *) &contents_hash_pos[32]);
+    keepass->contents_hash[5] = hex_to_u32 ((const u8 *) &contents_hash_pos[40]);
+    keepass->contents_hash[6] = hex_to_u32 ((const u8 *) &contents_hash_pos[48]);
+    keepass->contents_hash[7] = hex_to_u32 ((const u8 *) &contents_hash_pos[56]);
+
+    /* get length of contents following */
+    char *inline_flag_pos = strchr (contents_hash_pos, '*');
+
+    if (inline_flag_pos == NULL) return (PARSER_SALT_LENGTH);
+
+    contents_hash_len = inline_flag_pos - contents_hash_pos;
+
+    if (contents_hash_len != 64) return (PARSER_SALT_LENGTH);
+
+    inline_flag_pos++;
+
+    u32 inline_flag = atoi (inline_flag_pos);
+
+    if (inline_flag != 1) return (PARSER_SALT_LENGTH);
+
+    contents_len_pos = strchr (inline_flag_pos, '*');
+
+    if (contents_len_pos == NULL) return (PARSER_SALT_LENGTH);
+
+    contents_len_pos++;
+
+    contents_len = atoi (contents_len_pos);
+
+    if (contents_len > 50000) return (PARSER_SALT_LENGTH);
+
+    contents_pos = strchr (contents_len_pos, '*');
+
+    if (contents_pos == NULL) return (PARSER_SALT_LENGTH);
+
+    contents_pos++;
+
+    u32 i;
+
+    keepass->contents_len = contents_len;
+
+    contents_len = contents_len / 4;
+
+    keyfile_inline_pos = strchr (contents_pos, '*');
+
+    u32 real_contents_len;
+
+    if (keyfile_inline_pos == NULL)
+      real_contents_len = input_len - (contents_pos - input_buf);
+    else
+    {
+      real_contents_len = keyfile_inline_pos - contents_pos;
+      keyfile_inline_pos++;
+      is_keyfile_present = 1;
+    }
+
+    if (real_contents_len != keepass->contents_len * 2) return (PARSER_SALT_LENGTH);
+
+    for (i = 0; i < contents_len; i++)
+      keepass->contents[i] = hex_to_u32 ((const u8 *) &contents_pos[i * 8]);
+  }
+  else if (keepass->version == 2)
+  {
+    expected_bytes_pos = strchr (enc_iv_pos, '*');
+
+    if (expected_bytes_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+    enc_iv_len = expected_bytes_pos - enc_iv_pos;
+
+    if (enc_iv_len != 32) return (PARSER_SALT_LENGTH);
+
+    expected_bytes_pos++;
+
+    keepass->expected_bytes[0] = hex_to_u32 ((const u8 *) &expected_bytes_pos[ 0]);
+    keepass->expected_bytes[1] = hex_to_u32 ((const u8 *) &expected_bytes_pos[ 8]);
+    keepass->expected_bytes[2] = hex_to_u32 ((const u8 *) &expected_bytes_pos[16]);
+    keepass->expected_bytes[3] = hex_to_u32 ((const u8 *) &expected_bytes_pos[24]);
+    keepass->expected_bytes[4] = hex_to_u32 ((const u8 *) &expected_bytes_pos[32]);
+    keepass->expected_bytes[5] = hex_to_u32 ((const u8 *) &expected_bytes_pos[40]);
+    keepass->expected_bytes[6] = hex_to_u32 ((const u8 *) &expected_bytes_pos[48]);
+    keepass->expected_bytes[7] = hex_to_u32 ((const u8 *) &expected_bytes_pos[56]);
+
+    contents_hash_pos = strchr (expected_bytes_pos, '*');
+
+    if (contents_hash_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+
+    expected_bytes_len = contents_hash_pos - expected_bytes_pos;
+
+    if (expected_bytes_len != 64) return (PARSER_SALT_LENGTH);
+
+    contents_hash_pos++;
+
+    keepass->contents_hash[0] = hex_to_u32 ((const u8 *) &contents_hash_pos[ 0]);
+    keepass->contents_hash[1] = hex_to_u32 ((const u8 *) &contents_hash_pos[ 8]);
+    keepass->contents_hash[2] = hex_to_u32 ((const u8 *) &contents_hash_pos[16]);
+    keepass->contents_hash[3] = hex_to_u32 ((const u8 *) &contents_hash_pos[24]);
+    keepass->contents_hash[4] = hex_to_u32 ((const u8 *) &contents_hash_pos[32]);
+    keepass->contents_hash[5] = hex_to_u32 ((const u8 *) &contents_hash_pos[40]);
+    keepass->contents_hash[6] = hex_to_u32 ((const u8 *) &contents_hash_pos[48]);
+    keepass->contents_hash[7] = hex_to_u32 ((const u8 *) &contents_hash_pos[56]);
+
+    keyfile_inline_pos = strchr (contents_hash_pos, '*');
+
+    if (keyfile_inline_pos == NULL)
+      contents_hash_len = input_len - (int) (contents_hash_pos - input_buf);
+    else
+    {
+      contents_hash_len = keyfile_inline_pos - contents_hash_pos;
+      keyfile_inline_pos++;
+      is_keyfile_present = 1;
+    }
+    if (contents_hash_len != 64) return (PARSER_SALT_LENGTH);
+  }
+
+  if (is_keyfile_present != 0)
+  {
+    keyfile_len_pos = strchr (keyfile_inline_pos, '*');
+
+    keyfile_len_pos++;
+
+    keyfile_len = atoi (keyfile_len_pos);
+
+    keepass->keyfile_len = keyfile_len;
+
+    if (keyfile_len != 64) return (PARSER_SALT_LENGTH);
+
+    keyfile_pos = strchr (keyfile_len_pos, '*');
+
+    if (keyfile_pos == NULL) return (PARSER_SALT_LENGTH);
+
+    keyfile_pos++;
+
+    u32 real_keyfile_len = input_len - (keyfile_pos - input_buf);
+
+    if (real_keyfile_len != 64) return (PARSER_SALT_LENGTH);
+
+    keepass->keyfile[0] = hex_to_u32 ((const u8 *) &keyfile_pos[ 0]);
+    keepass->keyfile[1] = hex_to_u32 ((const u8 *) &keyfile_pos[ 8]);
+    keepass->keyfile[2] = hex_to_u32 ((const u8 *) &keyfile_pos[16]);
+    keepass->keyfile[3] = hex_to_u32 ((const u8 *) &keyfile_pos[24]);
+    keepass->keyfile[4] = hex_to_u32 ((const u8 *) &keyfile_pos[32]);
+    keepass->keyfile[5] = hex_to_u32 ((const u8 *) &keyfile_pos[40]);
+    keepass->keyfile[6] = hex_to_u32 ((const u8 *) &keyfile_pos[48]);
+    keepass->keyfile[7] = hex_to_u32 ((const u8 *) &keyfile_pos[56]);
+  }
+
+  digest[0] = keepass->enc_iv[0];
+  digest[1] = keepass->enc_iv[1];
+  digest[2] = keepass->enc_iv[2];
+  digest[3] = keepass->enc_iv[3];
+
+  salt->salt_buf[0] = keepass->transf_random_seed[0];
+  salt->salt_buf[1] = keepass->transf_random_seed[1];
+  salt->salt_buf[2] = keepass->transf_random_seed[2];
+  salt->salt_buf[3] = keepass->transf_random_seed[3];
+  salt->salt_buf[4] = keepass->transf_random_seed[4];
+  salt->salt_buf[5] = keepass->transf_random_seed[5];
+  salt->salt_buf[6] = keepass->transf_random_seed[6];
+  salt->salt_buf[7] = keepass->transf_random_seed[7];
+
+  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);
@@ -19202,9 +19945,10 @@ void *thread_keypress (void *p)
 
     if (ch ==  0) continue;
 
-    #ifdef _POSIX
-    if (ch != '\n')
-    #endif
+    //https://github.com/hashcat/oclHashcat/issues/302
+    //#ifdef _POSIX
+    //if (ch != '\n')
+    //#endif
 
     hc_thread_mutex_lock (mux_display);
 
@@ -19213,6 +19957,7 @@ void *thread_keypress (void *p)
     switch (ch)
     {
       case 's':
+      case '\r':
       case '\n':
 
         log_info ("");
@@ -19296,6 +20041,11 @@ void *thread_keypress (void *p)
         break;
     }
 
+    //https://github.com/hashcat/oclHashcat/issues/302
+    //#ifdef _POSIX
+    //if (ch != '\n')
+    //#endif
+
     hc_thread_mutex_unlock (mux_display);
   }
 
@@ -19374,7 +20124,7 @@ int conv_itoc (const u8 c)
 #define GET_P0_CONV(rule)      INCR_POS; rule_buf[rule_pos] = conv_itoc (((rule)->cmds[rule_cnt] >>  8) & 0xff)
 #define GET_P1_CONV(rule)      INCR_POS; rule_buf[rule_pos] = conv_itoc (((rule)->cmds[rule_cnt] >> 16) & 0xff)
 
-int cpu_rule_to_kernel_rule (char rule_buf[BUFSIZ], uint rule_len, kernel_rule_t *rule)
+int cpu_rule_to_kernel_rule (char *rule_buf, uint rule_len, kernel_rule_t *rule)
 {
   uint rule_pos;
   uint rule_cnt;
@@ -19590,11 +20340,11 @@ int cpu_rule_to_kernel_rule (char rule_buf[BUFSIZ], uint rule_len, kernel_rule_t
   return (0);
 }
 
-int kernel_rule_to_cpu_rule (char rule_buf[BUFSIZ], kernel_rule_t *rule)
+int kernel_rule_to_cpu_rule (char *rule_buf, kernel_rule_t *rule)
 {
   uint rule_cnt;
   uint rule_pos;
-  uint rule_len = BUFSIZ - 1; // maximum possible len
+  uint rule_len = HCBUFSIZ - 1; // maximum possible len
 
   char rule_cmd;