fixed problem with -m 5600 = NetNTLMv2 parser
[hashcat.git] / src / shared.c
index c50e32b..f1002b7 100644 (file)
@@ -1,22 +1,27 @@
 /**
- * Author......: Jens Steube <jens.steube@gmail.com>
+ * Authors.....: Jens Steube <jens.steube@gmail.com>
+ *               Gabriele Gristina <matrix@hashcat.net>
+ *               magnum <john.magnum@hushmail.com>
+ *
  * License.....: MIT
  */
 
+#ifdef OSX
+#include <stdio.h>
+#endif
+
 #include <shared.h>
 #include <limits.h>
 
-/**
- * tuning tools
- */
-
-#define GET_ACCEL(x) KERNEL_ACCEL_ ## x
-#define GET_LOOPS(x) KERNEL_LOOPS_ ## 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)));
@@ -91,7 +96,7 @@ void log_final (FILE *fp, const char *fmt, va_list ap)
     fputc ('\r', fp);
   }
 
-  char s[4096];
+  char s[4096] = { 0 };
 
   int max_len = (int) sizeof (s);
 
@@ -448,13 +453,13 @@ int base32_encode (u8 (*f) (const u8), const u8 *in_buf, int in_len, u8 *out_buf
     out_ptr += 8;
   }
 
-  int out_len = (in_len * 8) / 5;
+  int out_len = (int) (((0.5 + (float) in_len) * 8) / 5); // ceil (in_len * 8 / 5)
 
-  for (int i = 0; i < (7 - (in_len % 7)); i++)
+  while (out_len % 8)
   {
-    out_len++;
-
     out_buf[out_len] = '=';
+
+    out_len++;
   }
 
   return out_len;
@@ -515,13 +520,13 @@ int base64_encode (u8 (*f) (const u8), const u8 *in_buf, int in_len, u8 *out_buf
     out_ptr += 4;
   }
 
-  int out_len = (in_len * 8) / 6;
+  int out_len = (int) (((0.5 + (float) in_len) * 8) / 6); // ceil (in_len * 8 / 6)
 
-  for (int i = 0; i < (3 - (in_len % 3)); i++)
+  while (out_len % 4)
   {
-    out_len++;
-
     out_buf[out_len] = '=';
+
+    out_len++;
   }
 
   return out_len;
@@ -624,7 +629,7 @@ static void AES128_decrypt_cbc (const u32 key[4], const u32 iv[4], const u32 in[
 
   AES_set_decrypt_key ((const u8 *) key, 128, &skey);
 
-  u32 _iv[4];
+  u32 _iv[4] = { 0 };
 
   _iv[0] = iv[0];
   _iv[1] = iv[1];
@@ -633,8 +638,8 @@ static void AES128_decrypt_cbc (const u32 key[4], const u32 iv[4], const u32 in[
 
   for (int i = 0; i < 16; i += 4)
   {
-    u32 _in[4];
-    u32 _out[4];
+    u32 _in[4] = { 0 };
+    u32 _out[4] = { 0 };
 
     _in[0] = in[i + 0];
     _in[1] = in[i + 1];
@@ -664,9 +669,7 @@ static void juniper_decrypt_hash (char *in, char *out)
 {
   // base64 decode
 
-  u8 base64_buf[100];
-
-  memset (base64_buf, 0, sizeof (base64_buf));
+  u8 base64_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) in, DISPLAY_LEN_MIN_501, base64_buf);
 
@@ -680,7 +683,7 @@ static void juniper_decrypt_hash (char *in, char *out)
 
   // reversed key
 
-  u32 juniper_key[4];
+  u32 juniper_key[4] = { 0 };
 
   juniper_key[0] = byte_swap_32 (0xa6707a7e);
   juniper_key[1] = byte_swap_32 (0x8df91059);
@@ -2446,6 +2449,8 @@ int tty_getchar()
 
   DWORD num = 0;
 
+  memset (buf, 0, sizeof (buf));
+
   ReadConsoleInput (stdinHandle, buf, 100, &num);
 
   FlushConsoleInputBuffer (stdinHandle);
@@ -2601,7 +2606,7 @@ char *logfile_generate_topid ()
 
   char *topid = (char *) mymalloc (1 + 16 + 1);
 
-  sprintf (topid, "TOP%08x", id);
+  snprintf (topid, 1 + 16, "TOP%08x", id);
 
   return topid;
 }
@@ -2612,7 +2617,7 @@ char *logfile_generate_subid ()
 
   char *subid = (char *) mymalloc (1 + 16 + 1);
 
-  sprintf (subid, "SUB%08x", id);
+  snprintf (subid, 1 + 16, "SUB%08x", id);
 
   return subid;
 }
@@ -2621,6 +2626,36 @@ char *logfile_generate_subid ()
  * system
  */
 
+#if F_SETLKW
+void lock_file (FILE *fp)
+{
+  struct flock lock;
+
+  memset (&lock, 0, sizeof (struct flock));
+
+  lock.l_type = F_WRLCK;
+  while (fcntl(fileno(fp), F_SETLKW, &lock))
+  {
+    if (errno != EINTR)
+    {
+      log_error ("ERROR: failed acquiring write lock: %s", strerror (errno));
+
+      exit (-1);
+    }
+  }
+}
+
+void unlock_file (FILE *fp)
+{
+  struct flock lock;
+
+  memset (&lock, 0, sizeof (struct flock));
+
+  lock.l_type = F_UNLCK;
+  fcntl(fileno(fp), F_SETLK, &lock);
+}
+#endif // F_SETLKW
+
 #ifdef _WIN
 void fsync (int fd)
 {
@@ -2634,12 +2669,13 @@ void fsync (int fd)
  * thermal
  */
 
-#ifdef _WIN
+#ifdef HAVE_HWMON
+#if defined(_WIN) && defined(HAVE_NVAPI)
 int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 {
   NvU32 pGpuCount;
 
-  if (hc_NvAPI_EnumPhysicalGPUs (nvGPUHandle, &pGpuCount) != NVAPI_OK) return (0);
+  if (hm_NvAPI_EnumPhysicalGPUs (data.hm_nv, nvGPUHandle, &pGpuCount) != NVAPI_OK) return (0);
 
   if (pGpuCount == 0)
   {
@@ -2650,20 +2686,20 @@ int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 
   return (pGpuCount);
 }
-#endif
+#endif // _WIN && HAVE_NVAPI
 
-#ifdef LINUX
+#if defined(LINUX) && defined(HAVE_NVML)
 int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 {
   int pGpuCount = 0;
 
   for (uint i = 0; i < DEVICES_MAX; i++)
   {
-    if (hc_NVML_nvmlDeviceGetHandleByIndex (data.hm_dll_nv, 1, i, &nvGPUHandle[i]) != NVML_SUCCESS) break;
+    if (hm_NVML_nvmlDeviceGetHandleByIndex (data.hm_nv, 1, i, &nvGPUHandle[i]) != NVML_SUCCESS) break;
 
-    //can be used to determine if the device by index matches the cuda device by index
-    //char name[100]; memset (name, 0, sizeof (name));
-    //hc_NVML_nvmlDeviceGetName (data.hm_dll_nv, nvGPUHandle[i], name, sizeof (name) - 1);
+    // can be used to determine if the device by index matches the cuda device by index
+    // char name[100]; memset (name, 0, sizeof (name));
+    // hm_NVML_nvmlDeviceGetName (data.hm_nv, nvGPUHandle[i], name, sizeof (name) - 1);
 
     pGpuCount++;
   }
@@ -2677,52 +2713,12 @@ int hm_get_adapter_index_nv (HM_ADAPTER_NV nvGPUHandle[DEVICES_MAX])
 
   return (pGpuCount);
 }
-#endif
-
-void hm_close (HM_LIB hm_dll)
-{
-  #ifdef _POSIX
-  dlclose (hm_dll);
-
-  #elif _WIN
-  FreeLibrary (hm_dll);
-
-  #endif
-}
-
-HM_LIB hm_init (const cl_uint vendor_id)
-{
-  HM_LIB hm_dll = NULL;
-
-  if (vendor_id == VENDOR_ID_AMD)
-  {
-    #ifdef _POSIX
-    hm_dll = dlopen ("libatiadlxx.so", RTLD_LAZY | RTLD_GLOBAL);
-
-    #elif _WIN
-    hm_dll = LoadLibrary ("atiadlxx.dll");
-
-    if (hm_dll == NULL)
-    {
-      hm_dll = LoadLibrary ("atiadlxy.dll");
-    }
-
-    #endif
-  }
-
-  #ifdef LINUX
-  if (vendor_id == VENDOR_ID_NV)
-  {
-    hm_dll = dlopen ("libnvidia-ml.so", RTLD_LAZY | RTLD_GLOBAL);
-  }
-  #endif
-
-  return hm_dll;
-}
+#endif // LINUX && HAVE_NVML
 
-int get_adapters_num_amd (HM_LIB hm_dll_amd, int *iNumberAdapters)
+#ifdef HAVE_ADL
+int get_adapters_num_amd (void *adl, int *iNumberAdapters)
 {
-  if (hc_ADL_Adapter_NumberOfAdapters_Get (hm_dll_amd, iNumberAdapters) != ADL_OK) return -1;
+  if (hm_ADL_Adapter_NumberOfAdapters_Get ((ADL_PTR *) adl, iNumberAdapters) != ADL_OK) return -1;
 
   if (iNumberAdapters == 0)
   {
@@ -2743,7 +2739,7 @@ int hm_show_performance_level (HM_LIB hm_dll, int iAdapterIndex)
   lpOdParameters.iSize = sizeof (ADLODParameters);
   size_t plevels_size = 0;
 
-  if (hc_ADL_Overdrive_ODParameters_Get (hm_dll, iAdapterIndex, &lpOdParameters) != ADL_OK) return -1;
+  if (hm_ADL_Overdrive_ODParameters_Get (hm_dll, iAdapterIndex, &lpOdParameters) != ADL_OK) return -1;
 
   log_info ("[DEBUG] %s, adapter %d performance level (%d) : %s %s",
           __func__, iAdapterIndex,
@@ -2757,7 +2753,7 @@ int hm_show_performance_level (HM_LIB hm_dll, int iAdapterIndex)
 
   lpOdPerformanceLevels->iSize = sizeof (ADLODPerformanceLevels) + sizeof (ADLODPerformanceLevel) * (lpOdParameters.iNumberOfPerformanceLevels - 1);
 
-  if (hc_ADL_Overdrive_ODPerformanceLevels_Get (hm_dll, iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK) return -1;
+  if (hm_ADL_Overdrive_ODPerformanceLevels_Get (hm_dll, iAdapterIndex, 0, lpOdPerformanceLevels) != ADL_OK) return -1;
 
   for (int j = 0; j < lpOdParameters.iNumberOfPerformanceLevels; j++)
     log_info ("[DEBUG] %s, adapter %d, level %d : engine %d, memory %d, voltage: %d",
@@ -2770,13 +2766,13 @@ int hm_show_performance_level (HM_LIB hm_dll, int iAdapterIndex)
 }
 */
 
-LPAdapterInfo hm_get_adapter_info_amd (HM_LIB hm_dll_amd, int iNumberAdapters)
+LPAdapterInfo hm_get_adapter_info_amd (void *adl, int iNumberAdapters)
 {
   size_t AdapterInfoSize = iNumberAdapters * sizeof (AdapterInfo);
 
   LPAdapterInfo lpAdapterInfo = (LPAdapterInfo) mymalloc (AdapterInfoSize);
 
-  if (hc_ADL_Adapter_AdapterInfo_Get (hm_dll_amd, lpAdapterInfo, AdapterInfoSize) != ADL_OK) return NULL;
+  if (hm_ADL_Adapter_AdapterInfo_Get ((ADL_PTR *) adl, lpAdapterInfo, AdapterInfoSize) != ADL_OK) return NULL;
 
   return lpAdapterInfo;
 }
@@ -2935,7 +2931,7 @@ u32 *hm_get_list_valid_adl_adapters (int iNumberAdapters, int *num_adl_adapters,
   return adl_adapters;
 }
 
-int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
+int hm_check_fanspeed_control (void *adl, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
 {
   // loop through all valid devices
 
@@ -2953,7 +2949,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
 
     int opencl_device_index = i;
 
-    // if (hm_show_performance_level (hm_dll_amd, info.iAdapterIndex) != 0) return -1;
+    // if (hm_show_performance_level (adl, info.iAdapterIndex) != 0) return -1;
 
     // get fanspeed info
 
@@ -2965,7 +2961,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
 
       FanSpeedInfo.iSize = sizeof (ADLFanSpeedInfo);
 
-      if (hc_ADL_Overdrive5_FanSpeedInfo_Get (hm_dll_amd, info.iAdapterIndex, 0, &FanSpeedInfo) != ADL_OK) return -1;
+      if (hm_ADL_Overdrive5_FanSpeedInfo_Get (adl, info.iAdapterIndex, 0, &FanSpeedInfo) != ADL_OK) return -1;
 
       // check read and write capability in fanspeedinfo
 
@@ -2985,7 +2981,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
 
       memset (&faninfo, 0, sizeof (faninfo));
 
-      if (hc_ADL_Overdrive6_FanSpeed_Get (hm_dll_amd, info.iAdapterIndex, &faninfo) != ADL_OK) return -1;
+      if (hm_ADL_Overdrive6_FanSpeed_Get (adl, info.iAdapterIndex, &faninfo) != ADL_OK) return -1;
 
       // check read capability in fanspeedinfo
 
@@ -3003,7 +2999,7 @@ int hm_check_fanspeed_control (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *va
   return 0;
 }
 
-int hm_get_overdrive_version (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
+int hm_get_overdrive_version (void *adl, hm_attrs_t *hm_device, u32 *valid_adl_device_list, int num_adl_adapters, LPAdapterInfo lpAdapterInfo)
 {
   for (int i = 0; i < num_adl_adapters; i++)
   {
@@ -3019,7 +3015,7 @@ int hm_get_overdrive_version (HM_LIB hm_dll_amd, hm_attrs_t *hm_device, u32 *val
     int od_enabled   = 0;
     int od_version   = 0;
 
-    if (hc_ADL_Overdrive_Caps (hm_dll_amd, info.iAdapterIndex, &od_supported, &od_enabled, &od_version) != ADL_OK) return -1;
+    if (hm_ADL_Overdrive_Caps (adl, info.iAdapterIndex, &od_supported, &od_enabled, &od_version) != ADL_OK) return -1;
 
     // store the overdrive version in hm_device
 
@@ -3058,14 +3054,16 @@ int hm_get_adapter_index_amd (hm_attrs_t *hm_device, u32 *valid_adl_device_list,
 
   return num_adl_adapters;
 }
+#endif // HAVE_ADL
 
 int hm_get_temperature_with_device_id (const uint device_id)
 {
   if ((data.devices_param[device_id].device_type & CL_DEVICE_TYPE_GPU) == 0) return -1;
 
+  #ifdef HAVE_ADL
   if (data.devices_param[device_id].vendor_id == VENDOR_ID_AMD)
   {
-    if (data.hm_dll_amd)
+    if (data.hm_amd)
     {
       if (data.hm_device[device_id].od_version == 5)
       {
@@ -3073,7 +3071,7 @@ int hm_get_temperature_with_device_id (const uint device_id)
 
         Temperature.iSize = sizeof (ADLTemperature);
 
-        if (hc_ADL_Overdrive5_Temperature_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, 0, &Temperature) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive5_Temperature_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, 0, &Temperature) != ADL_OK) return -1;
 
         return Temperature.iTemperature / 1000;
       }
@@ -3081,23 +3079,26 @@ int hm_get_temperature_with_device_id (const uint device_id)
       {
         int Temperature = 0;
 
-        if (hc_ADL_Overdrive6_Temperature_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &Temperature) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive6_Temperature_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &Temperature) != ADL_OK) return -1;
 
         return Temperature / 1000;
       }
     }
   }
-  else if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
+  #endif
+
+  #if defined(HAVE_NVML) || defined(HAVE_NVAPI)
+  if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
   {
-    #ifdef LINUX
+    #if defined(LINUX) && defined(HAVE_NVML)
     int temperature = 0;
 
-    hc_NVML_nvmlDeviceGetTemperature (data.hm_dll_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
 
-    #ifdef WIN
+    #if defined(WIN) && defined(HAVE_NVAPI)
     NV_GPU_THERMAL_SETTINGS pThermalSettings;
 
     pThermalSettings.version = NV_GPU_THERMAL_SETTINGS_VER;
@@ -3105,11 +3106,12 @@ int hm_get_temperature_with_device_id (const uint device_id)
     pThermalSettings.sensor[0].controller = NVAPI_THERMAL_CONTROLLER_UNKNOWN;
     pThermalSettings.sensor[0].target = NVAPI_THERMAL_TARGET_GPU;
 
-    if (hc_NvAPI_GPU_GetThermalSettings (data.hm_device[device_id].adapter_index.nv, 0, &pThermalSettings) != NVAPI_OK) return -1;
+    if (hm_NvAPI_GPU_GetThermalSettings (data.hm_nv, data.hm_device[device_id].adapter_index.nv, 0, &pThermalSettings) != NVAPI_OK) return -1;
 
     return pThermalSettings.sensor[0].currentTemp;
-    #endif
+    #endif // WIN && HAVE_NVAPI
   }
+  #endif // HAVE_NVML || HAVE_NVAPI
 
   return -1;
 }
@@ -3121,9 +3123,10 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
 
   if (data.hm_device[device_id].fan_supported == 1)
   {
+    #ifdef HAVE_ADL
     if (data.devices_param[device_id].vendor_id == VENDOR_ID_AMD)
     {
-      if (data.hm_dll_amd)
+      if (data.hm_amd)
       {
         if (data.hm_device[device_id].od_version == 5)
         {
@@ -3135,7 +3138,7 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
           lpFanSpeedValue.iSpeedType = ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
           lpFanSpeedValue.iFlags     = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
 
-          if (hc_ADL_Overdrive5_FanSpeed_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
+          if (hm_ADL_Overdrive5_FanSpeed_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
 
           return lpFanSpeedValue.iFanSpeed;
         }
@@ -3145,30 +3148,37 @@ int hm_get_fanspeed_with_device_id (const uint device_id)
 
           memset (&faninfo, 0, sizeof (faninfo));
 
-          if (hc_ADL_Overdrive6_FanSpeed_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &faninfo) != ADL_OK) return -1;
+          if (hm_ADL_Overdrive6_FanSpeed_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &faninfo) != ADL_OK) return -1;
 
           return faninfo.iFanSpeedPercent;
         }
       }
     }
-    else if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
+    #endif // HAVE_ADL
+
+    #if defined(HAVE_NVML) || defined(HAVE_NVAPI)
+    if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
     {
-      #ifdef LINUX
+      #if defined(LINUX) && defined(HAVE_NVML)
       int speed = 0;
 
-      hc_NVML_nvmlDeviceGetFanSpeed (data.hm_dll_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
 
-      #ifdef WIN
-      NvU32 speed = 0;
+      #if defined(WIN) && defined(HAVE_NVAPI)
 
-      hc_NvAPI_GPU_GetTachReading (data.hm_device[device_id].adapter_index.nv, &speed);
+      NV_GPU_COOLER_SETTINGS pCoolerSettings;
 
-      return speed;
+      pCoolerSettings.Version = GPU_COOLER_SETTINGS_VER | sizeof (NV_GPU_COOLER_SETTINGS);
+
+      hm_NvAPI_GPU_GetCoolerSettings (data.hm_nv, data.hm_device[device_id].adapter_index.nv, 0, &pCoolerSettings);
+
+      return pCoolerSettings.Cooler[0].CurrentLevel;
       #endif
     }
+    #endif // HAVE_NVML || HAVE_NVAPI
   }
 
   return -1;
@@ -3178,48 +3188,54 @@ int hm_get_utilization_with_device_id (const uint device_id)
 {
   if ((data.devices_param[device_id].device_type & CL_DEVICE_TYPE_GPU) == 0) return -1;
 
+  #ifdef HAVE_ADL
   if (data.devices_param[device_id].vendor_id == VENDOR_ID_AMD)
   {
-    if (data.hm_dll_amd)
+    if (data.hm_amd)
     {
       ADLPMActivity PMActivity;
 
       PMActivity.iSize = sizeof (ADLPMActivity);
 
-      if (hc_ADL_Overdrive_CurrentActivity_Get (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &PMActivity) != ADL_OK) return -1;
+      if (hm_ADL_Overdrive_CurrentActivity_Get (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &PMActivity) != ADL_OK) return -1;
 
       return PMActivity.iActivityPercent;
     }
   }
-  else if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
+  #endif // HAVE_ADL
+
+  #if defined(HAVE_NVML) || defined(HAVE_NVAPI)
+  if (data.devices_param[device_id].vendor_id == VENDOR_ID_NV)
   {
-    #ifdef LINUX
+    #if defined(LINUX) && defined(HAVE_NVML)
     nvmlUtilization_t utilization;
 
-    hc_NVML_nvmlDeviceGetUtilizationRates (data.hm_dll_nv, data.hm_device[device_id].adapter_index.nv, &utilization);
+    hm_NVML_nvmlDeviceGetUtilizationRates (data.hm_nv, data.hm_device[device_id].adapter_index.nv, &utilization);
 
     return utilization.gpu;
     #endif
 
-    #ifdef WIN
+    #if defined(WIN) && defined(HAVE_NVAPI)
     NV_GPU_DYNAMIC_PSTATES_INFO_EX pDynamicPstatesInfoEx;
 
     pDynamicPstatesInfoEx.version = NV_GPU_DYNAMIC_PSTATES_INFO_EX_VER;
 
-    if (hc_NvAPI_GPU_GetDynamicPstatesInfoEx (data.hm_device[device_id].adapter_index.nv, &pDynamicPstatesInfoEx) != NVAPI_OK) return -1;
+    if (hm_NvAPI_GPU_GetDynamicPstatesInfoEx (data.hm_nv, data.hm_device[device_id].adapter_index.nv, &pDynamicPstatesInfoEx) != NVAPI_OK) return -1;
 
     return pDynamicPstatesInfoEx.utilization[0].percentage;
     #endif
   }
+  #endif // HAVE_NVML || HAVE_NVAPI
 
   return -1;
 }
 
+#ifdef HAVE_ADL
 int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed)
 {
   if (data.hm_device[device_id].fan_supported == 1)
   {
-    if (data.hm_dll_amd)
+    if (data.hm_amd)
     {
       if (data.hm_device[device_id].od_version == 5)
       {
@@ -3232,7 +3248,7 @@ int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed
         lpFanSpeedValue.iFlags     = ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
         lpFanSpeedValue.iFanSpeed  = fanspeed;
 
-        if (hc_ADL_Overdrive5_FanSpeed_Set (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive5_FanSpeed_Set (data.hm_amd, data.hm_device[device_id].adapter_index.amd, 0, &lpFanSpeedValue) != ADL_OK) return -1;
 
         return 0;
       }
@@ -3245,7 +3261,7 @@ int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed
         fan_speed_value.iSpeedType = ADL_OD6_FANSPEED_TYPE_PERCENT;
         fan_speed_value.iFanSpeed  = fanspeed;
 
-        if (hc_ADL_Overdrive6_FanSpeed_Set (data.hm_dll_amd, data.hm_device[device_id].adapter_index.amd, &fan_speed_value) != ADL_OK) return -1;
+        if (hm_ADL_Overdrive6_FanSpeed_Set (data.hm_amd, data.hm_device[device_id].adapter_index.amd, &fan_speed_value) != ADL_OK) return -1;
 
         return 0;
       }
@@ -3254,6 +3270,7 @@ int hm_set_fanspeed_with_device_id_amd (const uint device_id, const int fanspeed
 
   return -1;
 }
+#endif
 
 // helper function for status display
 
@@ -3270,6 +3287,7 @@ void hm_device_val_to_str (char *target_buf, int max_buf_size, char *suffix, int
     snprintf (target_buf, max_buf_size, "%2d%s", value, suffix);
   }
 }
+#endif // HAVE_HWMON
 
 /**
  * maskprocessor
@@ -3310,8 +3328,6 @@ void mp_add_cs_buf (uint *in_buf, size_t in_len, cs_t *css, int css_cnt)
 
   uint *css_uniq = (uint *) mymalloc (css_uniq_sz);
 
-  memset (css_uniq, 0, css_uniq_sz);
-
   size_t i;
 
   for (i = 0; i < cs->cs_len; i++)
@@ -3575,9 +3591,7 @@ void mp_setup_sys (cs_t *mp_sys)
 {
   uint pos;
   uint chr;
-  uint donec[CHARSIZ];
-
-  memset (donec, 0, sizeof (donec));
+  uint donec[CHARSIZ] = { 0 };
 
   for (pos = 0, chr =  'a'; chr <=  'z'; chr++) { donec[chr] = 1;
                                                   mp_sys[0].cs_buf[pos++] = chr;
@@ -3612,9 +3626,7 @@ void mp_setup_usr (cs_t *mp_sys, cs_t *mp_usr, char *buf, uint index)
   }
   else
   {
-    char mp_file[1024];
-
-    memset (mp_file, 0, sizeof (mp_file));
+    char mp_file[1024] = { 0 };
 
     size_t len = fread (mp_file, 1, sizeof (mp_file) - 1, fp);
 
@@ -3796,9 +3808,7 @@ void sp_setup_tbl (const char *shared_dir, char *hcstat, uint disable, uint clas
 
   if (hcstat == NULL)
   {
-    char hcstat_tmp[256];
-
-    memset (hcstat_tmp, 0, sizeof (hcstat_tmp));
+    char hcstat_tmp[256] = { 0 };
 
     snprintf (hcstat_tmp, sizeof (hcstat_tmp) - 1, "%s/%s", shared_dir, SP_HCSTAT);
 
@@ -3818,6 +3828,8 @@ void sp_setup_tbl (const char *shared_dir, char *hcstat, uint disable, uint clas
   {
     log_error ("%s: Could not load data", hcstat);
 
+    fclose (fd);
+
     exit (-1);
   }
 
@@ -3825,6 +3837,8 @@ void sp_setup_tbl (const char *shared_dir, char *hcstat, uint disable, uint clas
   {
     log_error ("%s: Could not load data", hcstat);
 
+    fclose (fd);
+
     exit (-1);
   }
 
@@ -4099,18 +4113,31 @@ char *get_exec_path ()
 
   #ifdef LINUX
 
-  char tmp[32];
+  char tmp[32] = { 0 };
 
-  sprintf (tmp, "/proc/%d/exe", getpid ());
+  snprintf (tmp, sizeof (tmp) - 1, "/proc/%d/exe", getpid ());
 
   const int len = readlink (tmp, exec_path, exec_path_len - 1);
 
-  #endif
-
-  #ifdef WIN
+  #elif WIN
 
   const int len = GetModuleFileName (NULL, exec_path, exec_path_len - 1);
 
+  #elif OSX
+
+  uint size = exec_path_len;
+
+  if (_NSGetExecutablePath (exec_path, &size) != 0)
+  {
+    log_error("! executable path buffer too small\n");
+
+    exit (-1);
+  }
+
+  const int len = strlen (exec_path);
+
+  #else
+  #error Your Operating System is not supported or detected
   #endif
 
   exec_path[len] = 0;
@@ -4144,9 +4171,11 @@ char *get_profile_dir (const char *homedir)
 {
   #define DOT_HASHCAT ".hashcat"
 
-  char *profile_dir = (char *) mymalloc (strlen (homedir) + 1 + strlen (DOT_HASHCAT) + 1);
+  size_t len = strlen (homedir) + 1 + strlen (DOT_HASHCAT) + 1;
+
+  char *profile_dir = (char *) mymalloc (len + 1);
 
-  sprintf (profile_dir, "%s/%s", homedir, DOT_HASHCAT);
+  snprintf (profile_dir, len, "%s/%s", homedir, DOT_HASHCAT);
 
   return profile_dir;
 }
@@ -4155,13 +4184,44 @@ char *get_session_dir (const char *profile_dir)
 {
   #define SESSIONS_FOLDER "sessions"
 
-  char *session_dir = (char *) mymalloc (strlen (profile_dir) + 1 + strlen (SESSIONS_FOLDER) + 1);
+  size_t len = strlen (profile_dir) + 1 + strlen (SESSIONS_FOLDER) + 1;
 
-  sprintf (session_dir, "%s/%s", profile_dir, SESSIONS_FOLDER);
+  char *session_dir = (char *) mymalloc (len + 1);
+
+  snprintf (session_dir, len, "%s/%s", profile_dir, SESSIONS_FOLDER);
 
   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;
@@ -4200,15 +4260,36 @@ void truecrypt_crc32 (const char *filename, u8 keytab[64])
   myfree (buf);
 }
 
+#ifdef OSX
+int pthread_setaffinity_np (pthread_t thread, size_t cpu_size, cpu_set_t *cpu_set)
+{
+  int core;
+
+  for (core = 0; core < (8 * (int)cpu_size); core++)
+    if (CPU_ISSET(core, cpu_set)) break;
+
+  thread_affinity_policy_data_t policy = { core };
+
+  const int rc = thread_policy_set (pthread_mach_thread_np (thread), THREAD_AFFINITY_POLICY, (thread_policy_t) &policy, 1);
+
+  if (data.quiet == 0)
+  {
+    if (rc != KERN_SUCCESS)
+    {
+      log_error ("ERROR: %s : %d", "thread_policy_set()", rc);
+    }
+  }
+
+  return rc;
+}
+#endif
+
 void set_cpu_affinity (char *cpu_affinity)
 {
   #ifdef WIN
   DWORD_PTR aff_mask = 0;
-  #endif
-
-  #ifdef LINUX
+  #elif _POSIX
   cpu_set_t cpuset;
-
   CPU_ZERO (&cpuset);
   #endif
 
@@ -4226,9 +4307,7 @@ void set_cpu_affinity (char *cpu_affinity)
       {
         #ifdef WIN
         aff_mask = 0;
-        #endif
-
-        #ifdef LINUX
+        #elif _POSIX
         CPU_ZERO (&cpuset);
         #endif
 
@@ -4244,9 +4323,7 @@ void set_cpu_affinity (char *cpu_affinity)
 
       #ifdef WIN
       aff_mask |= 1 << (cpu_id - 1);
-      #endif
-
-      #ifdef LINUX
+      #elif _POSIX
       CPU_SET ((cpu_id - 1), &cpuset);
       #endif
 
@@ -4258,9 +4335,7 @@ void set_cpu_affinity (char *cpu_affinity)
   #ifdef WIN
   SetProcessAffinityMask (GetCurrentProcess (), aff_mask);
   SetThreadAffinityMask (GetCurrentThread (), aff_mask);
-  #endif
-
-  #ifdef LINUX
+  #elif _POSIX
   pthread_t thread = pthread_self ();
   pthread_setaffinity_np (thread, sizeof (cpu_set_t), &cpuset);
   #endif
@@ -4279,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;
@@ -4294,7 +4377,7 @@ int sort_by_salt (const void *v1, const void *v2)
 
   uint n;
 
-  n = 12;
+  n = 16;
 
   while (n--)
   {
@@ -4324,7 +4407,7 @@ int sort_by_salt_buf (const void *v1, const void *v2)
   const salt_t *s1 = h1->salt;
   const salt_t *s2 = h2->salt;
 
-  uint n = 12;
+  uint n = 16;
 
   while (n--)
   {
@@ -4344,7 +4427,7 @@ int sort_by_hash_t_salt (const void *v1, const void *v2)
   const salt_t *s2 = h2->salt;
 
   // testphase: this should work
-  uint n = 12;
+  uint n = 16;
 
   while (n--)
   {
@@ -4377,8 +4460,8 @@ int sort_by_hash_t_salt_hccap (const void *v1, const void *v2)
   const salt_t *s1 = h1->salt;
   const salt_t *s2 = h2->salt;
 
-  // 12 - 2 (since last 2 uints contain the digest)
-  uint n = 10;
+  // 16 - 2 (since last 2 uints contain the digest)
+  uint n = 14;
 
   while (n--)
   {
@@ -4472,7 +4555,7 @@ int sort_by_dictstat (const void *s1, const void *s2)
   dictstat_t *d1 = (dictstat_t *) s1;
   dictstat_t *d2 = (dictstat_t *) s2;
 
-  #ifdef _POSIX
+  #ifdef LINUX
   d2->stat.st_atim = d1->stat.st_atim;
   #else
   d2->stat.st_atime = d1->stat.st_atime;
@@ -4687,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;
@@ -4698,6 +4815,8 @@ void format_debug (char *debug_file, uint debug_mode, unsigned char *orig_plain_
   if (debug_file != NULL)
   {
     debug_fp = fopen (debug_file, "ab");
+
+    lock_file (debug_fp);
   }
   else
   {
@@ -4835,7 +4954,7 @@ void format_output (FILE *out_fp, char *out_buf, unsigned char *plain_ptr, const
 
     #ifdef _POSIX
     #ifdef __x86_64__
-    fprintf (out_fp, "%lu", crackpos);
+    fprintf (out_fp, "%lu", (unsigned long) crackpos);
     #else
     fprintf (out_fp, "%llu", crackpos);
     #endif
@@ -5073,9 +5192,7 @@ void handle_left_request_lm (pot_t *pot, uint pot_cnt, char *input_buf, int inpu
 
   uint user_len = input_len - 32;
 
-  char hash_output[user_len + 33];
-
-  memset (hash_output, 0, sizeof (hash_output));
+  char *hash_output = (char *) mymalloc (33);
 
   memcpy (hash_output, input_buf, input_len);
 
@@ -5099,6 +5216,8 @@ void handle_left_request_lm (pot_t *pot, uint pot_cnt, char *input_buf, int inpu
 
   format_output (out_fp, hash_output, NULL, 0, 0, NULL, 0);
 
+  myfree (hash_output);
+
   if (weak_hash_found == 1) myfree (pot_right_ptr);
 }
 
@@ -5202,7 +5321,7 @@ cl_device_type setup_device_types_filter (char *opencl_device_types)
   else
   {
     // Do not use CPU by default, this often reduces GPU performance because
-    // the CPU is to busy to handle GPU synchronization
+    // the CPU is too busy to handle GPU synchronization
 
     device_types_filter = CL_DEVICE_TYPE_ALL & ~CL_DEVICE_TYPE_CPU;
   }
@@ -5405,14 +5524,31 @@ char **scan_directory (const char *path)
 
   int num_files = 0;
 
-  DIR *d;
+  DIR *d = NULL;
 
   if ((d = opendir (tmp_path)) != NULL)
   {
+    #ifdef OSX
+    struct dirent e;
+
+    for (;;) {
+      memset (&e, 0, sizeof (e));
+      struct dirent *de = NULL;
+
+      if (readdir_r (d, &e, &de) != 0)
+      {
+        log_error ("ERROR: readdir_r() failed");
+
+        break;
+      }
+
+      if (de == NULL) break;
+    #else
     struct dirent *de;
 
     while ((de = readdir (d)) != NULL)
     {
+    #endif
       if ((strcmp (de->d_name, ".") == 0) || (strcmp (de->d_name, "..") == 0)) continue;
 
       int path_size = strlen (tmp_path) + 1 + strlen (de->d_name);
@@ -5495,6 +5631,10 @@ char *stroptitype (const uint opti_type)
     case OPTI_TYPE_SINGLE_SALT:       return ((char *) OPTI_STR_SINGLE_SALT);       break;
     case OPTI_TYPE_BRUTE_FORCE:       return ((char *) OPTI_STR_BRUTE_FORCE);       break;
     case OPTI_TYPE_RAW_HASH:          return ((char *) OPTI_STR_RAW_HASH);          break;
+    case OPTI_TYPE_USES_BITS_8:       return ((char *) OPTI_STR_USES_BITS_8);       break;
+    case OPTI_TYPE_USES_BITS_16:      return ((char *) OPTI_STR_USES_BITS_16);      break;
+    case OPTI_TYPE_USES_BITS_32:      return ((char *) OPTI_STR_USES_BITS_32);      break;
+    case OPTI_TYPE_USES_BITS_64:      return ((char *) OPTI_STR_USES_BITS_64);      break;
   }
 
   return (NULL);
@@ -5708,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");
@@ -5727,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");
@@ -5745,7 +5889,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
   uint len = 4096;
 
-  uint digest_buf[64];
+  uint digest_buf[64] = { 0 };
 
   u64 *digest_buf64 = (u64 *) digest_buf;
 
@@ -5962,9 +6106,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     if (opts_type & OPTS_TYPE_ST_HEX)
     {
-      char tmp[64];
-
-      memset (tmp, 0, sizeof (tmp));
+      char tmp[64] = { 0 };
 
       for (uint i = 0, j = 0; i < len; i += 1, j += 2)
       {
@@ -5987,24 +6129,17 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   // some modes require special encoding
   //
 
-  uint out_buf_plain[256];
-  uint out_buf_salt[256];
-
-  char tmp_buf[1024];
+  uint out_buf_plain[256] = { 0 };
+  uint out_buf_salt[256] = { 0 };
 
-  memset (out_buf_plain, 0, sizeof (out_buf_plain));
-  memset (out_buf_salt,  0, sizeof (out_buf_salt));
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  char tmp_buf[1024] = { 0 };
 
   char *ptr_plain = (char *) out_buf_plain;
   char *ptr_salt  = (char *) out_buf_salt;
 
   if (hash_mode == 22)
   {
-    char username[30];
-
-    memset (username, 0, sizeof (username));
+    char username[30] = { 0 };
 
     memcpy (username, salt.salt_buf, salt.salt_len - 22);
 
@@ -6064,7 +6199,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 101)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6080,7 +6215,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 111)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6138,7 +6273,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 133)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6160,7 +6295,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     memset (tmp_buf, 0, sizeof (tmp_buf));
 
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6178,7 +6313,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 400)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6191,7 +6326,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 500)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6246,7 +6381,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     memset (tmp_buf, 0, sizeof (tmp_buf));
 
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6275,7 +6410,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     memset (tmp_buf, 0, sizeof (tmp_buf));
 
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6290,7 +6425,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 1600)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6444,7 +6579,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     wpa_t *wpa = &wpas[salt_pos];
 
-    uint pke[25];
+    uint pke[25] = { 0 };
 
     char *pke_ptr = (char *) pke;
 
@@ -6453,8 +6588,8 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       pke[i] = byte_swap_32 (wpa->pke[i]);
     }
 
-    unsigned char mac1[6];
-    unsigned char mac2[6];
+    unsigned char mac1[6] = { 0 };
+    unsigned char mac2[6] = { 0 };
 
     memcpy (mac1, pke_ptr + 23, 6);
     memcpy (mac2, pke_ptr + 29, 6);
@@ -6663,15 +6798,10 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     netntlm_t *netntlm = &netntlms[salt_pos];
 
-    char user_buf[64];
-    char domain_buf[64];
-    char srvchall_buf[1024];
-    char clichall_buf[1024];
-
-    memset (user_buf,     0, sizeof (user_buf));
-    memset (domain_buf,   0, sizeof (domain_buf));
-    memset (srvchall_buf, 0, sizeof (srvchall_buf));
-    memset (clichall_buf, 0, sizeof (clichall_buf));
+    char user_buf[64] = { 0 };
+    char domain_buf[64] = { 0 };
+    char srvchall_buf[1024] = { 0 };
+    char clichall_buf[1024] = { 0 };
 
     for (uint i = 0, j = 0; j < netntlm->user_len; i += 1, j += 2)
     {
@@ -6719,15 +6849,10 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     netntlm_t *netntlm = &netntlms[salt_pos];
 
-    char user_buf[64];
-    char domain_buf[64];
-    char srvchall_buf[1024];
-    char clichall_buf[1024];
-
-    memset (user_buf,     0, sizeof (user_buf));
-    memset (domain_buf,   0, sizeof (domain_buf));
-    memset (srvchall_buf, 0, sizeof (srvchall_buf));
-    memset (clichall_buf, 0, sizeof (clichall_buf));
+    char user_buf[64] = { 0 };
+    char domain_buf[64] = { 0 };
+    char srvchall_buf[1024] = { 0 };
+    char clichall_buf[1024] = { 0 };
 
     for (uint i = 0, j = 0; j < netntlm->user_len; i += 1, j += 2)
     {
@@ -6809,7 +6934,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 6300)
   {
-    // the encoder is a bit to intelligent, it expects the input data in the wrong BOM
+    // the encoder is a bit too intelligent, it expects the input data in the wrong BOM
 
     digest_buf[0] = byte_swap_32 (digest_buf[0]);
     digest_buf[1] = byte_swap_32 (digest_buf[1]);
@@ -6871,7 +6996,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     pbkdf2_sha512_t *pbkdf2_sha512  = &pbkdf2_sha512s[salt_pos];
 
-    uint esalt[16];
+    uint esalt[8] = { 0 };
 
     esalt[0] = byte_swap_32 (pbkdf2_sha512->salt_buf[0]);
     esalt[1] = byte_swap_32 (pbkdf2_sha512->salt_buf[1]);
@@ -6980,7 +7105,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     u8 *ptr_timestamp = (u8 *) krb5pa->timestamp;
     u8 *ptr_checksum  = (u8 *) krb5pa->checksum;
 
-    char data[128];
+    char data[128] = { 0 };
 
     char *ptr_data = data;
 
@@ -7068,7 +7193,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     cloudkey_t *cloudkey = &cloudkeys[salt_pos];
 
-    char data_buf[4096];
+    char data_buf[4096] = { 0 };
 
     for (int i = 0, j = 0; i < 512; i += 1, j += 8)
     {
@@ -7172,7 +7297,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     androidfde_t *androidfde = &androidfdes[salt_pos];
 
-    char tmp[3073];
+    char tmp[3073] = { 0 };
 
     for (uint i = 0, j = 0; i < 384; i += 1, j += 8)
     {
@@ -7199,9 +7324,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     uint r = salt.scrypt_r;
     uint p = salt.scrypt_p;
 
-    char base64_salt[32];
-
-    memset (base64_salt, 0, 32);
+    char base64_salt[32] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) salt.salt_buf, salt.salt_len, (u8 *) base64_salt);
 
@@ -7253,8 +7376,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     digest_buf[7] = byte_swap_32 (digest_buf[7]);
     digest_buf[8] = 0; // needed for base64_encode ()
 
-    char tmp_buf[64];
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[64] = { 0 };
 
     base64_encode (int_to_itoa64, (const u8 *) digest_buf, 32, (u8 *) tmp_buf);
     tmp_buf[43] = 0; // cut it here
@@ -7275,8 +7397,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     digest_buf[7] = byte_swap_32 (digest_buf[7]);
     digest_buf[8] = 0; // needed for base64_encode ()
 
-    char tmp_buf[64];
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[64] = { 0 };
 
     base64_encode (int_to_itoa64, (const u8 *) digest_buf, 32, (u8 *) tmp_buf);
     tmp_buf[43] = 0; // cut it here
@@ -7526,8 +7647,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     digest_buf[7] = byte_swap_32 (digest_buf[7]);
     digest_buf[8] = 0; // needed for base64_encode ()
 
-    char tmp_buf[64];
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[64] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) digest_buf, 32, (u8 *) tmp_buf);
 
@@ -7555,15 +7675,13 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     // challenge
 
-    char challenge[100];
-
-    memset (challenge, 0, sizeof (challenge));
+    char challenge[100] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) salt.salt_buf, salt.salt_len, (u8 *) challenge);
 
     // response
 
-    char tmp_buf[100];
+    char tmp_buf[100] = { 0 };
 
     uint tmp_len = snprintf (tmp_buf, 100, "%s %08x%08x%08x%08x",
       (char *) cram_md5->user,
@@ -7572,9 +7690,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       digest_buf[2],
       digest_buf[3]);
 
-    char response[100];
-
-    memset (response, 0, sizeof (response));
+    char response[100] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) tmp_buf, tmp_len, (u8 *) response);
 
@@ -7582,9 +7698,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   }
   else if (hash_mode == 10300)
   {
-    char tmp_buf[100];
-
-    memset (tmp_buf, 0, sizeof (tmp_buf));
+    char tmp_buf[100] = { 0 };
 
     memcpy (tmp_buf +  0, digest_buf, 20);
     memcpy (tmp_buf + 20, salt.salt_buf, salt.salt_len);
@@ -7593,9 +7707,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
 
     // base64 encode it
 
-    char base64_encoded[100];
-
-    memset (base64_encoded, 0, sizeof (base64_encoded));
+    char base64_encoded[100] = { 0 };
 
     base64_encode (int_to_base64, (const u8 *) tmp_buf, tmp_len, (u8 *) base64_encoded);
 
@@ -8046,7 +8158,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
   {
     // encode iteration count
 
-    char salt_iter[5];
+    char salt_iter[5] = { 0 };
 
     salt_iter[0] = int_to_itoa64 ((salt.salt_iter      ) & 0x3f);
     salt_iter[1] = int_to_itoa64 ((salt.salt_iter >>  6) & 0x3f);
@@ -8183,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)
@@ -8382,7 +8547,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
       digest_buf[ 2] = byte_swap_32 (digest_buf[ 2]);
       digest_buf[ 3] = byte_swap_32 (digest_buf[ 3]);
 
-      char buf[16];
+      char buf[16] = { 0 };
 
       memcpy (buf + 0, salt.salt_buf, 5);
       memcpy (buf + 5, digest_buf, 9);
@@ -8398,9 +8563,7 @@ void ascii_digest (char out_buf[4096], uint salt_pos, uint digest_pos)
     }
     else if (hash_type == HASH_TYPE_LOTUS8)
     {
-      char buf[52];
-
-      memset (buf, 0, sizeof (buf));
+      char buf[52] = { 0 };
 
       // salt
 
@@ -8464,7 +8627,7 @@ void to_hccap_t (hccap_t *hccap, uint salt_pos, uint digest_pos)
 
   if (wpa->keyver != 1)
   {
-    uint eapol_tmp[64];
+    uint eapol_tmp[64] = { 0 };
 
     for (uint i = 0; i < 64; i++)
     {
@@ -8478,7 +8641,7 @@ 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];
+  uint pke_tmp[25] = { 0 };
 
   for (int i = 5; i < 25; i++)
   {
@@ -8500,7 +8663,7 @@ void to_hccap_t (hccap_t *hccap, uint salt_pos, uint digest_pos)
 
   if (wpa->keyver != 1)
   {
-    uint digest_tmp[4];
+    uint digest_tmp[4] = { 0 };
 
     digest_tmp[0] = byte_swap_32 (digest_ptr[0]);
     digest_tmp[1] = byte_swap_32 (digest_ptr[1]);
@@ -8610,9 +8773,9 @@ void myquit ()
 
 void load_kernel (const char *kernel_file, int num_devices, size_t *kernel_lengths, const u8 **kernel_sources)
 {
-  FILE *fp;
+  FILE *fp = fopen (kernel_file, "rb");
 
-  if ((fp = fopen (kernel_file, "rb")) != NULL)
+  if (fp != NULL)
   {
     struct stat st;
 
@@ -8654,12 +8817,16 @@ void load_kernel (const char *kernel_file, int num_devices, size_t *kernel_lengt
 
 void writeProgramBin (char *dst, u8 *binary, size_t binary_size)
 {
-  FILE *fp = fopen (dst, "wb");
+  if (binary_size > 0)
+  {
+    FILE *fp = fopen (dst, "wb");
 
-  fwrite (binary, sizeof (u8), binary_size, fp);
+    lock_file (fp);
+    fwrite (binary, sizeof (u8), binary_size, fp);
 
-  fflush (fp);
-  fclose (fp);
+    fflush (fp);
+    fclose (fp);
+  }
 }
 
 /**
@@ -8689,13 +8856,11 @@ restore_data_t *init_restore (int argc, char **argv)
 
       if (rd->pid)
       {
-        char pidbin[BUFSIZ];
+        char pidbin[BUFSIZ] = { 0 };
 
-        int pidbin_len;
+        int pidbin_len = -1;
 
         #ifdef _POSIX
-        memset (pidbin, 0, sizeof (pidbin));
-
         snprintf (pidbin, sizeof (pidbin) - 1, "/proc/%d/cmdline", rd->pid);
 
         FILE *fd = fopen (pidbin, "rb");
@@ -8727,11 +8892,9 @@ restore_data_t *init_restore (int argc, char **argv)
         #elif _WIN
         HANDLE hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, rd->pid);
 
-        char pidbin2[BUFSIZ];
-
-        int pidbin2_len;
+        char pidbin2[BUFSIZ] = { 0 };
 
-        memset (pidbin2, 0, sizeof (pidbin2));
+        int pidbin2_len = -1;
 
         pidbin_len = GetModuleFileName (NULL, pidbin, BUFSIZ);
         pidbin2_len = GetModuleFileNameEx (hProcess, NULL, pidbin2, BUFSIZ);
@@ -8805,7 +8968,7 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
 
   for (uint i = 0; i < rd->argc; i++)
   {
-    char buf[BUFSIZ];
+    char buf[BUFSIZ] = { 0 };
 
     if (fgets (buf, BUFSIZ - 1, fp) == NULL)
     {
@@ -8823,7 +8986,7 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
 
   fclose (fp);
 
-  char new_cwd[256];
+  char new_cwd[1024] = { 0 };
 
   char *nwd = getcwd (new_cwd, sizeof (new_cwd));
 
@@ -8844,7 +9007,6 @@ void read_restore (const char *eff_restore_file, restore_data_t *rd)
     log_info ("WARNING: Found old restore file, updating path to %s...", new_cwd);
   }
 
-
   if (chdir (rd->cwd))
   {
     log_error ("ERROR: cannot chdir to %s: %s", rd->cwd, strerror (errno));
@@ -8956,397 +9118,321 @@ void check_checkpoint ()
 }
 
 /**
- * adjustments
+ * tuning db
  */
 
-uint set_kernel_accel (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     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);
-  }
+    tuning_db_alias_t *alias = &tuning_db->alias_buf[i];
 
-  return 0;
-}
+    myfree (alias->device_name);
+    myfree (alias->alias_name);
+  }
 
-uint set_kernel_loops (uint hash_mode)
-{
-  switch (hash_mode)
+  for (i = 0; i < tuning_db->entry_cnt; 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);
+    tuning_db_entry_t *entry = &tuning_db->entry_buf[i];
+
+    myfree (entry->device_name);
   }
 
-  return 0;
+  myfree (tuning_db->alias_buf);
+  myfree (tuning_db->entry_buf);
+
+  myfree (tuning_db);
 }
 
-/**
- * parser
- */
+tuning_db_t *tuning_db_alloc (FILE *fp)
+{
+  tuning_db_t *tuning_db = (tuning_db_t *) mymalloc (sizeof (tuning_db_t));
+
+  int num_lines = count_lines (fp);
+
+  // 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;
+
+  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");
+
+  if (fp == NULL)
+  {
+    log_error ("%s: %s", tuning_db_file, strerror (errno));
+
+    exit (-1);
+  }
+
+  tuning_db_t *tuning_db = tuning_db_alloc (fp);
+
+  rewind (fp);
+
+  int line_num = 0;
+
+  while (!feof (fp))
+  {
+    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;
+    }
+  }
+
+  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;
+}
+
+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_param->device_name);
+
+  int device_name_length = strlen (device_name_nospace);
+
+  int i;
+
+  for (i = 0; i < device_name_length; i++)
+  {
+    if (device_name_nospace[i] == ' ') device_name_nospace[i] = '_';
+  }
+
+  // find out if there's an alias configured
+
+  tuning_db_alias_t a;
+
+  a.device_name = device_name_nospace;
+
+  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);
+
+  char *alias_name = (alias == NULL) ? NULL : alias->alias_name;
+
+  // attack-mode 6 and 7 are attack-mode 1 basically
+
+  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++)
+  {
+    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;
+    }
+  }
+
+  // free converted device_name
+
+  myfree (device_name_nospace);
+
+  return entry;
+}
+
+/**
+ * parser
+ */
 
 uint parse_and_store_salt (char *out, char *in, uint salt_len)
 {
-  u8 tmp[256];
+  u8 tmp[256] = { 0 };
 
   if (salt_len > sizeof (tmp))
   {
     return UINT_MAX;
   }
 
-  memset (tmp, 0, sizeof (tmp));
   memcpy (tmp, in, salt_len);
 
   if (data.opts_type & OPTS_TYPE_ST_HEX)
@@ -9479,9 +9565,7 @@ int bcrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (bf64_to_int, (const u8 *) salt_pos, 22, tmp_buf);
 
@@ -9520,9 +9604,7 @@ int cisco4_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (itoa64_to_int, (const u8 *) input_buf, 43, tmp_buf);
 
@@ -9709,7 +9791,7 @@ int netscreen_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // unscramble
 
-  char clean_input_buf[32];
+  char clean_input_buf[32] = { 0 };
 
   char sig[6] = { 'n', 'r', 'c', 's', 't', 'n' };
   int  pos[6] = {   0,   6,  12,  17,  23,  29 };
@@ -9798,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;
 
@@ -9931,7 +10015,7 @@ int wpa_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   /*
     http://www.one-net.eu/jsw/j_sec/m_ptype.html
     The phrase "Pairwise key expansion"
-    Access Point Address (Referred to as Authenticator Address AA)
+    Access Point Address (referred to as Authenticator Address AA)
     Supplicant Address (referred to as Supplicant Address SA)
     Access Point Nonce (referred to as Authenticator Anonce)
     Wireless Device Nonce (referred to as Supplicant Nonce Snonce)
@@ -9939,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;
@@ -10016,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);
 }
@@ -10044,17 +10142,10 @@ int psafe2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     exit (-1);
   }
 
-  typedef struct
-  {
-    u32 random[2];
-    u32 hash[5];
-    u32 salt[5];   // unused, but makes better valid check
-    u32 iv[2];     // unused, but makes better valid check
-
-  } psafe2_hdr;
-
   psafe2_hdr buf;
 
+  memset (&buf, 0, sizeof (psafe2_hdr));
+
   int n = fread (&buf, sizeof (psafe2_hdr), 1, fp);
 
   fclose (fp);
@@ -10181,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;
@@ -10213,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, '$');
 
@@ -10321,9 +10414,7 @@ int episerver_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) hash_pos, 27, tmp_buf);
 
@@ -10365,9 +10456,7 @@ int descrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = 2;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (itoa64_to_int, (const u8 *) input_buf + 2, 11, tmp_buf);
 
@@ -10706,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;
 
@@ -10806,7 +10895,7 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   /* special case, last 8 byte do not need to be checked since they are brute-forced next */
 
-  uint digest_tmp[2];
+  uint digest_tmp[2] = { 0 };
 
   digest_tmp[0] = hex_to_u32 ((const u8 *) &hash_pos[32]);
   digest_tmp[1] = hex_to_u32 ((const u8 *) &hash_pos[40]);
@@ -10820,26 +10909,16 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   {
     if ((netntlm->chall_buf[2] == 0) && (netntlm->chall_buf[3] == 0) && (netntlm->chall_buf[4] == 0) && (netntlm->chall_buf[5] == 0))
     {
-      uint w[16];
+      uint w[16] = { 0 };
 
       w[ 0] = netntlm->chall_buf[6];
       w[ 1] = netntlm->chall_buf[7];
       w[ 2] = netntlm->chall_buf[0];
       w[ 3] = netntlm->chall_buf[1];
       w[ 4] = 0x80;
-      w[ 5] = 0;
-      w[ 6] = 0;
-      w[ 7] = 0;
-      w[ 8] = 0;
-      w[ 9] = 0;
-      w[10] = 0;
-      w[11] = 0;
-      w[12] = 0;
-      w[13] = 0;
       w[14] = 16 * 8;
-      w[15] = 0;
 
-      uint dgst[4];
+      uint dgst[4] = { 0 };
 
       dgst[0] = MAGIC_A;
       dgst[1] = MAGIC_B;
@@ -10862,8 +10941,8 @@ int netntlmv1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
     transform_netntlmv1_key ((u8 *) key_md4, (u8 *) key_des);
 
-    uint Kc[16];
-    uint Kd[16];
+    uint Kc[16] = { 0 };
+    uint Kd[16] = { 0 };
 
     _des_keysetup (key_des, Kc, Kd, c_skb);
 
@@ -10952,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;
 
@@ -11383,9 +11462,7 @@ int ipb2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *salt_buf = input_buf + 32 + 1;
 
-  uint salt_pc_block[16];
-
-  memset (salt_pc_block, 0, sizeof (salt_pc_block));
+  uint salt_pc_block[16] = { 0 };
 
   char *salt_pc_block_ptr = (char *) salt_pc_block;
 
@@ -11397,12 +11474,7 @@ int ipb2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_pc_block[14] = salt_len * 8;
 
-  uint salt_pc_digest[4];
-
-  salt_pc_digest[0] = MAGIC_A;
-  salt_pc_digest[1] = MAGIC_B;
-  salt_pc_digest[2] = MAGIC_C;
-  salt_pc_digest[3] = MAGIC_D;
+  uint salt_pc_digest[4] = { MAGIC_A, MAGIC_B, MAGIC_C, MAGIC_D };
 
   md5_64 (salt_pc_block, salt_pc_digest);
 
@@ -11463,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)
@@ -11515,9 +11606,7 @@ int sha1b64_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) input_buf + 5, input_len - 5, tmp_buf);
 
@@ -11548,15 +11637,19 @@ int sha1b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   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);
 
@@ -12098,10 +12191,12 @@ int ikepsk_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *in_off[9];
 
-  size_t in_len[9];
+  size_t in_len[9] = { 0 };
 
   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;
@@ -12115,9 +12210,7 @@ int ikepsk_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     in_len[i] = strlen (in_off[i]);
   }
 
-  char *ptr;
-
-  ptr = (char *) ikepsk->msg_buf;
+  char *ptr = (char *) ikepsk->msg_buf;
 
   for (i = 0; i < in_len[0]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[0] + i);
   for (i = 0; i < in_len[1]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[1] + i);
@@ -12185,10 +12278,12 @@ int ikepsk_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *in_off[9];
 
-  size_t in_len[9];
+  size_t in_len[9] = { 0 };
 
   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;
@@ -12202,9 +12297,7 @@ int ikepsk_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     in_len[i] = strlen (in_off[i]);
   }
 
-  char *ptr;
-
-  ptr = (char *) ikepsk->msg_buf;
+  char *ptr = (char *) ikepsk->msg_buf;
 
   for (i = 0; i < in_len[0]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[0] + i);
   for (i = 0; i < in_len[1]; i += 2) *ptr++ = hex_to_u8 ((const u8 *) in_off[1] + i);
@@ -12356,7 +12449,7 @@ int truecrypt_parse_hash_1k (char *input_buf, uint input_len, hash_t *hash_buf)
     exit (-1);
   }
 
-  char buf[512];
+  char buf[512] = { 0 };
 
   int n = fread (buf, 1, sizeof (buf), fp);
 
@@ -12403,7 +12496,7 @@ int truecrypt_parse_hash_2k (char *input_buf, uint input_len, hash_t *hash_buf)
     exit (-1);
   }
 
-  char buf[512];
+  char buf[512] = { 0 };
 
   int n = fread (buf, 1, sizeof (buf), fp);
 
@@ -12960,9 +13053,7 @@ int episerver4_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = salt_len;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) hash_pos, 43, tmp_buf);
 
@@ -13063,12 +13154,12 @@ int sha512b64s_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[120];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[120] = { 0 };
 
   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]);
@@ -13089,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);
 
@@ -13941,9 +14036,7 @@ int nsec3_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   // and one that includes only the real salt (stored into salt_buf[]).
   // the domain-name length is put into array position 7 of salt_buf_pc[] since there is not salt_pc_len
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base32_decode (itoa32_to_int, (const u8 *) hashbuf_pos, 32, tmp_buf);
 
@@ -14143,9 +14236,7 @@ int lotus6_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[120];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[120] = { 0 };
 
   base64_decode (lotus64_to_int, (const u8 *) input_buf + 2, input_len - 3, tmp_buf);
 
@@ -14174,9 +14265,7 @@ int lotus8_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt_t *salt = hash_buf->salt;
 
-  u8 tmp_buf[120];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[120] = { 0 };
 
   base64_decode (lotus64_to_int, (const u8 *) input_buf + 2, input_len - 3, tmp_buf);
 
@@ -14190,7 +14279,7 @@ int lotus8_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // iteration
 
-  char tmp_iter_buf[11];
+  char tmp_iter_buf[11] = { 0 };
 
   memcpy (tmp_iter_buf, tmp_buf + 16, 10);
 
@@ -14363,9 +14452,9 @@ int peoplesoft_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 *digest = (u32 *) hash_buf->digest;
 
-  u8 tmp_buf[100];
+  salt_t *salt = hash_buf->salt;
 
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (base64_to_int, (const u8 *) input_buf, input_len, tmp_buf);
 
@@ -14383,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);
 }
 
@@ -14586,9 +14679,7 @@ int scrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode
 
-  u8 tmp_buf[33];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[33] = { 0 };
 
   int tmp_len = base64_decode (base64_to_int, (const u8 *) saltbuf_pos, hash_pos - saltbuf_pos, tmp_buf);
 
@@ -14626,7 +14717,7 @@ int juniper_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
    * parse line
    */
 
-  char decrypted[76]; // iv + hash
+  char decrypted[76] = { 0 }; // iv + hash
 
   juniper_decrypt_hash (input_buf, decrypted);
 
@@ -14700,9 +14791,7 @@ int cisco8_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   uint hash_len = input_len - 3 - salt_len - 1;
 
@@ -14760,9 +14849,7 @@ int cisco9_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   uint hash_len = input_len - 3 - salt_len - 1;
 
@@ -15885,9 +15972,7 @@ int djangopbkdf2_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   uint hash_len = input_len - (hash_pos - input_buf);
 
@@ -15979,9 +16064,7 @@ int crammd5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // base64 decode salt
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   salt_len = base64_decode (base64_to_int, (const u8 *) salt_pos, salt_len, tmp_buf);
 
@@ -16059,9 +16142,7 @@ int saph_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   u32 base64_len = input_len - (base64_pos - input_buf);
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   u32 decoded_len = base64_decode (base64_to_int, (const u8 *) base64_pos, base64_len, tmp_buf);
 
@@ -16798,14 +16879,14 @@ int pdf14_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // md5
 
-  uint salt_pc_block[32];
+  uint salt_pc_block[32] = { 0 };
 
   char *salt_pc_ptr = (char *) salt_pc_block;
 
   memcpy (salt_pc_ptr, padding, 32);
   memcpy (salt_pc_ptr + 32, pdf->id_buf, pdf->id_len);
 
-  uint salt_pc_digest[4];
+  uint salt_pc_digest[4] = { 0 };
 
   md5_complete_no_limit (salt_pc_digest, salt_pc_block, 32 + pdf->id_len);
 
@@ -17095,9 +17176,7 @@ int pbkdf2_sha256_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -17439,9 +17518,8 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // work with a temporary copy of input_buf (s.t. we can manipulate it directly)
 
-  char temp_input_buf[input_len + 1];
+  char *temp_input_buf = (char *) mymalloc (input_len + 1);
 
-  memset (temp_input_buf, 0, sizeof (temp_input_buf));
   memcpy (temp_input_buf, input_buf, input_len);
 
   // URI_server:
@@ -17450,177 +17528,307 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   char *URI_client_pos = strchr (URI_server_pos, '*');
 
-  if (URI_client_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_client_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_client_pos[0] = 0;
   URI_client_pos++;
 
   uint URI_server_len = strlen (URI_server_pos);
 
-  if (URI_server_len > 512) return (PARSER_SALT_LENGTH);
+  if (URI_server_len > 512)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_client:
 
   char *user_pos = strchr (URI_client_pos, '*');
 
-  if (user_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (user_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   user_pos[0] = 0;
   user_pos++;
 
   uint URI_client_len = strlen (URI_client_pos);
 
-  if (URI_client_len > 512) return (PARSER_SALT_LENGTH);
+  if (URI_client_len > 512)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // user:
 
   char *realm_pos = strchr (user_pos, '*');
 
-  if (realm_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (realm_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   realm_pos[0] = 0;
   realm_pos++;
 
   uint user_len = strlen (user_pos);
 
-  if (user_len > 116) return (PARSER_SALT_LENGTH);
+  if (user_len > 116)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // realm:
 
   char *method_pos = strchr (realm_pos, '*');
 
-  if (method_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (method_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   method_pos[0] = 0;
   method_pos++;
 
   uint realm_len = strlen (realm_pos);
 
-  if (realm_len > 116) return (PARSER_SALT_LENGTH);
+  if (realm_len > 116)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // method:
 
   char *URI_prefix_pos = strchr (method_pos, '*');
 
-  if (URI_prefix_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_prefix_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_prefix_pos[0] = 0;
   URI_prefix_pos++;
 
   uint method_len = strlen (method_pos);
 
-  if (method_len > 246) return (PARSER_SALT_LENGTH);
+  if (method_len > 246)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_prefix:
 
   char *URI_resource_pos = strchr (URI_prefix_pos, '*');
 
-  if (URI_resource_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_resource_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_resource_pos[0] = 0;
   URI_resource_pos++;
 
   uint URI_prefix_len = strlen (URI_prefix_pos);
 
-  if (URI_prefix_len > 245) return (PARSER_SALT_LENGTH);
+  if (URI_prefix_len > 245)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_resource:
 
   char *URI_suffix_pos = strchr (URI_resource_pos, '*');
 
-  if (URI_suffix_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (URI_suffix_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   URI_suffix_pos[0] = 0;
   URI_suffix_pos++;
 
   uint URI_resource_len = strlen (URI_resource_pos);
 
-  if (URI_resource_len <   1) return (PARSER_SALT_LENGTH);
-  if (URI_resource_len > 246) return (PARSER_SALT_LENGTH);
+  if (URI_resource_len < 1 || URI_resource_len > 246)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // URI_suffix:
 
   char *nonce_pos = strchr (URI_suffix_pos, '*');
 
-  if (nonce_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (nonce_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   nonce_pos[0] = 0;
   nonce_pos++;
 
   uint URI_suffix_len = strlen (URI_suffix_pos);
 
-  if (URI_suffix_len > 245) return (PARSER_SALT_LENGTH);
+  if (URI_suffix_len > 245)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // nonce:
 
   char *nonce_client_pos = strchr (nonce_pos, '*');
 
-  if (nonce_client_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (nonce_client_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   nonce_client_pos[0] = 0;
   nonce_client_pos++;
 
   uint nonce_len = strlen (nonce_pos);
 
-  if (nonce_len <  1) return (PARSER_SALT_LENGTH);
-  if (nonce_len > 50) return (PARSER_SALT_LENGTH);
+  if (nonce_len < 1 || nonce_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // nonce_client:
 
   char *nonce_count_pos = strchr (nonce_client_pos, '*');
 
-  if (nonce_count_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (nonce_count_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   nonce_count_pos[0] = 0;
   nonce_count_pos++;
 
   uint nonce_client_len = strlen (nonce_client_pos);
 
-  if (nonce_client_len > 50) return (PARSER_SALT_LENGTH);
+  if (nonce_client_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // nonce_count:
 
   char *qop_pos = strchr (nonce_count_pos, '*');
 
-  if (qop_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (qop_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   qop_pos[0] = 0;
   qop_pos++;
 
   uint nonce_count_len = strlen (nonce_count_pos);
 
-  if (nonce_count_len > 50) return (PARSER_SALT_LENGTH);
+  if (nonce_count_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // qop:
 
   char *directive_pos = strchr (qop_pos, '*');
 
-  if (directive_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (directive_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   directive_pos[0] = 0;
   directive_pos++;
 
   uint qop_len = strlen (qop_pos);
 
-  if (qop_len > 50) return (PARSER_SALT_LENGTH);
+  if (qop_len > 50)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   // directive
 
   char *digest_pos = strchr (directive_pos, '*');
 
-  if (digest_pos == NULL) return (PARSER_SEPARATOR_UNMATCHED);
+  if (digest_pos == NULL)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SEPARATOR_UNMATCHED);
+  }
 
   digest_pos[0] = 0;
   digest_pos++;
 
   uint directive_len = strlen (directive_pos);
 
-  if (directive_len != 3) return (PARSER_SALT_LENGTH);
+  if (directive_len != 3)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   if (memcmp (directive_pos, "MD5", 3))
   {
     log_info ("ERROR: only the MD5 directive is currently supported\n");
 
+    myfree (temp_input_buf);
+
     return (PARSER_SIP_AUTH_DIRECTIVE);
   }
 
@@ -17634,9 +17842,7 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   uint md5_remaining_len = md5_max_len;
 
-  uint tmp_md5_buf[md5_max_len / 4];
-
-  memset (tmp_md5_buf, 0, sizeof (tmp_md5_buf));
+  uint tmp_md5_buf[64] = { 0 };
 
   char *tmp_md5_ptr = (char *) tmp_md5_buf;
 
@@ -17671,7 +17877,7 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
     md5_len += 1 + URI_suffix_len;
   }
 
-  uint tmp_digest[4];
+  uint tmp_digest[4] = { 0 };
 
   md5_complete_no_limit (tmp_digest, tmp_md5_buf, md5_len);
 
@@ -17696,7 +17902,12 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   {
     esalt_len = 1 + nonce_len + 1 + nonce_count_len + 1 + nonce_client_len + 1 + qop_len + 1 + 32;
 
-    if (esalt_len > max_esalt_len) return (PARSER_SALT_LENGTH);
+    if (esalt_len > max_esalt_len)
+    {
+      myfree (temp_input_buf);
+
+      return (PARSER_SALT_LENGTH);
+    }
 
     snprintf (esalt_buf_ptr, max_esalt_len, ":%s:%s:%s:%s:%08x%08x%08x%08x",
       nonce_pos,
@@ -17712,7 +17923,12 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   {
     esalt_len = 1 + nonce_len + 1 + 32;
 
-    if (esalt_len > max_esalt_len) return (PARSER_SALT_LENGTH);
+    if (esalt_len > max_esalt_len)
+    {
+      myfree (temp_input_buf);
+
+      return (PARSER_SALT_LENGTH);
+    }
 
     snprintf (esalt_buf_ptr, max_esalt_len, ":%s:%08x%08x%08x%08x",
       nonce_pos,
@@ -17738,7 +17954,12 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   uint max_salt_len = 119;
 
-  if (salt_len > max_salt_len) return (PARSER_SALT_LENGTH);
+  if (salt_len > max_salt_len)
+  {
+    myfree (temp_input_buf);
+
+    return (PARSER_SALT_LENGTH);
+  }
 
   snprintf (sip_salt_ptr, max_salt_len + 1, "%s:%s:", user_pos, realm_pos);
 
@@ -17777,6 +17998,8 @@ int sip_auth_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   digest[2] = byte_swap_32 (digest[2]);
   digest[3] = byte_swap_32 (digest[3]);
 
+  myfree (temp_input_buf);
+
   return (PARSER_OK);
 }
 
@@ -18115,9 +18338,7 @@ int pbkdf2_md5_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -18199,9 +18420,7 @@ int pbkdf2_sha1_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -18288,9 +18507,7 @@ int pbkdf2_sha512_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   // decode hash
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   int hash_len = base64_decode (base64_to_int, (const u8 *) hash_pos, hash_b64_len, tmp_buf);
 
@@ -18408,9 +18625,7 @@ int bsdicrypt_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
 
   salt->salt_len = 4;
 
-  u8 tmp_buf[100];
-
-  memset (tmp_buf, 0, sizeof (tmp_buf));
+  u8 tmp_buf[100] = { 0 };
 
   base64_decode (itoa64_to_int, (const u8 *) input_buf + 9, 11, tmp_buf);
 
@@ -18609,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);
@@ -18644,7 +19033,7 @@ int cf10_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
    * we can precompute the first sha256 transform
    */
 
-  uint w[16];
+  uint w[16] = { 0 };
 
   w[ 0] = byte_swap_32 (salt->salt_buf[ 0]);
   w[ 1] = byte_swap_32 (salt->salt_buf[ 1]);
@@ -18663,16 +19052,7 @@ int cf10_parse_hash (char *input_buf, uint input_len, hash_t *hash_buf)
   w[14] = byte_swap_32 (salt->salt_buf[14]);
   w[15] = byte_swap_32 (salt->salt_buf[15]);
 
-  uint pc256[8];
-
-  pc256[0] = SHA256M_A;
-  pc256[1] = SHA256M_B;
-  pc256[2] = SHA256M_C;
-  pc256[3] = SHA256M_D;
-  pc256[4] = SHA256M_E;
-  pc256[5] = SHA256M_F;
-  pc256[6] = SHA256M_G;
-  pc256[7] = SHA256M_H;
+  uint pc256[8] = { SHA256M_A, SHA256M_B, SHA256M_C, SHA256M_D, SHA256M_E, SHA256M_F, SHA256M_G, SHA256M_H };
 
   sha256_64 (w, pc256);
 
@@ -18912,7 +19292,7 @@ BOOL WINAPI sigHandler_default (DWORD sig)
       /*
        * special case see: https://stackoverflow.com/questions/3640633/c-setconsolectrlhandler-routine-issue/5610042#5610042
        * if the user interacts w/ the user-interface (GUI/cmd), we need to do the finalization job within this signal handler
-       * function otherwise it is to late (e.g. after returning from this function)
+       * function otherwise it is too late (e.g. after returning from this function)
        */
 
       myabort ();
@@ -19925,7 +20305,7 @@ int mangle_dupeblock_prepend (char arr[BLOCK_SIZE], int arr_len, int ulen)
 
   if ((arr_len + ulen) >= BLOCK_SIZE) return (arr_len);
 
-  char cs[100];
+  char cs[100] = { 0 };
 
   memcpy (cs, arr, ulen);
 
@@ -20183,13 +20563,13 @@ int generate_random_rule (char rule_buf[RP_RULE_BUFSIZ], u32 rp_gen_func_min, u3
 
 int _old_apply_rule (char *rule, int rule_len, char in[BLOCK_SIZE], int in_len, char out[BLOCK_SIZE])
 {
-  char mem[BLOCK_SIZE];
+  char mem[BLOCK_SIZE] = { 0 };
 
   if (in == NULL) return (RULE_RC_REJECT_ERROR);
 
   if (out == NULL) return (RULE_RC_REJECT_ERROR);
 
-  if (in_len < 1) return (RULE_RC_REJECT_ERROR);
+  if (in_len < 1 || in_len > BLOCK_SIZE) return (RULE_RC_REJECT_ERROR);
 
   if (rule_len < 1) return (RULE_RC_REJECT_ERROR);
 
@@ -20202,7 +20582,7 @@ int _old_apply_rule (char *rule, int rule_len, char in[BLOCK_SIZE], int in_len,
 
   for (rule_pos = 0; rule_pos < rule_len; rule_pos++)
   {
-    int upos; int upos2;
+    int upos, upos2;
     int ulen;
 
     switch (rule[rule_pos])