From 7d9461f8b9cbffbd77fc2f99bbca9d3ff50b80d7 Mon Sep 17 00:00:00 2001 From: Jens Steube Date: Sun, 26 Jan 2020 18:38:47 +0100 Subject: [PATCH] Add -m 11600 optimized kernel --- OpenCL/m11600-optimized.cl | 255 +++++++++++++++++++++++++++++++++++ OpenCL/m11600-pure.cl | 77 ++++++----- src/interface.c | 42 +++--- src/modules/module_11600.c | 42 +++++- tools/test_modules/m11600.pm | 2 +- 5 files changed, 354 insertions(+), 64 deletions(-) create mode 100644 OpenCL/m11600-optimized.cl diff --git a/OpenCL/m11600-optimized.cl b/OpenCL/m11600-optimized.cl new file mode 100644 index 000000000..835522f44 --- /dev/null +++ b/OpenCL/m11600-optimized.cl @@ -0,0 +1,255 @@ +/** + * Author......: See docs/credits.txt + * License.....: MIT + */ + +#ifdef KERNEL_STATIC +#include "inc_vendor.h" +#include "inc_types.h" +#include "inc_platform.cl" +#include "inc_common.cl" +#include "inc_hash_sha256.cl" +#endif + +typedef struct seven_zip_tmp +{ + u32 h[8]; + + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + + int len; + +} seven_zip_tmp_t; + +typedef struct +{ + u32 ukey[8]; + + u32 hook_success; + +} seven_zip_hook_t; + +#define PUTCHAR(a,p,c) ((u8 *)(a))[(p)] = (u8) (c) +#define GETCHAR(a,p) ((u8 *)(a))[(p)] + +#define PUTCHAR_BE(a,p,c) ((u8 *)(a))[(p) ^ 3] = (u8) (c) +#define GETCHAR_BE(a,p) ((u8 *)(a))[(p) ^ 3] + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) + +KERNEL_FQ void m11600_init (KERN_ATTR_TMPS_HOOKS (seven_zip_tmp_t, seven_zip_hook_t)) +{ + /** + * base + */ + + const u64 gid = get_global_id (0); + + if (gid >= gid_max) return; + + tmps[gid].h[0] = SHA256M_A; + tmps[gid].h[1] = SHA256M_B; + tmps[gid].h[2] = SHA256M_C; + tmps[gid].h[3] = SHA256M_D; + tmps[gid].h[4] = SHA256M_E; + tmps[gid].h[5] = SHA256M_F; + tmps[gid].h[6] = SHA256M_G; + tmps[gid].h[7] = SHA256M_H; + + tmps[gid].len = 0; +} + +KERNEL_FQ void m11600_loop (KERN_ATTR_TMPS_HOOKS (seven_zip_tmp_t, seven_zip_hook_t)) +{ + const u64 gid = get_global_id (0); + + if (gid >= gid_max) return; + + u32 pw_buf[5]; + + pw_buf[0] = pws[gid].i[0]; + pw_buf[1] = pws[gid].i[1]; + pw_buf[2] = pws[gid].i[2]; + pw_buf[3] = pws[gid].i[3]; + pw_buf[4] = pws[gid].i[4]; + + const u32 pw_len = MIN (pws[gid].pw_len, 20); + + // this is large enough to hold all possible w[] arrays for 64 iterations + + #define LARGEBLOCK_ELEMS ((40 + 8) * 16) + + u32 largeblock[LARGEBLOCK_ELEMS]; + + u8 *ptr = (u8 *) largeblock; + + for (u32 i = 0; i < LARGEBLOCK_ELEMS; i++) largeblock[i] = 0; + + u32 loop_pos_pos = loop_pos; + + for (u32 i = 0, p = 0; i < 64; i++) + { + for (u32 j = 0; j < pw_len; j++, p += 2) + { + PUTCHAR_BE (largeblock, p, GETCHAR (pw_buf, j)); + } + + const u8 byte2 = unpack_v8c_from_v32_S (loop_pos_pos); + const u8 byte3 = unpack_v8d_from_v32_S (loop_pos_pos); + + PUTCHAR_BE (largeblock, p + 2, byte2); + PUTCHAR_BE (largeblock, p + 3, byte3); + + loop_pos_pos++; + + p += 8; + } + + u32 h[8]; + + h[0] = tmps[gid].h[0]; + h[1] = tmps[gid].h[1]; + h[2] = tmps[gid].h[2]; + h[3] = tmps[gid].h[3]; + h[4] = tmps[gid].h[4]; + h[5] = tmps[gid].h[5]; + h[6] = tmps[gid].h[6]; + h[7] = tmps[gid].h[7]; + + const int iter64 = (pw_len * 2) + 8; + + loop_pos_pos = loop_pos; + + for (u32 i = 0; i < loop_cnt; i += 64) + { + // iteration set + for (u32 i = 0, p = pw_len * 2; i < 64; i++, p += iter64) + { + const u8 byte0 = unpack_v8a_from_v32_S (loop_pos_pos); + const u8 byte1 = unpack_v8b_from_v32_S (loop_pos_pos); + + PUTCHAR_BE (largeblock, p + 0, byte0); + PUTCHAR_BE (largeblock, p + 1, byte1); + + loop_pos_pos++; + } + + // full 64 byte buffer + for (int j = 0, j16 = 0; j < iter64; j++, j16 += 16) + { + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + + w0[0] = largeblock[j16 + 0]; + w0[1] = largeblock[j16 + 1]; + w0[2] = largeblock[j16 + 2]; + w0[3] = largeblock[j16 + 3]; + w1[0] = largeblock[j16 + 4]; + w1[1] = largeblock[j16 + 5]; + w1[2] = largeblock[j16 + 6]; + w1[3] = largeblock[j16 + 7]; + w2[0] = largeblock[j16 + 8]; + w2[1] = largeblock[j16 + 9]; + w2[2] = largeblock[j16 + 10]; + w2[3] = largeblock[j16 + 11]; + w3[0] = largeblock[j16 + 12]; + w3[1] = largeblock[j16 + 13]; + w3[2] = largeblock[j16 + 14]; + w3[3] = largeblock[j16 + 15]; + + sha256_transform (w0, w1, w2, w3, h); + } + } + + tmps[gid].len += loop_cnt * iter64; + + tmps[gid].h[0] = h[0]; + tmps[gid].h[1] = h[1]; + tmps[gid].h[2] = h[2]; + tmps[gid].h[3] = h[3]; + tmps[gid].h[4] = h[4]; + tmps[gid].h[5] = h[5]; + tmps[gid].h[6] = h[6]; + tmps[gid].h[7] = h[7]; +} + +KERNEL_FQ void m11600_hook23 (KERN_ATTR_TMPS_HOOKS (seven_zip_tmp_t, seven_zip_hook_t)) +{ + const u64 gid = get_global_id (0); + + if (gid >= gid_max) return; + + /** + * context load + */ + + u32 h[8]; + + h[0] = tmps[gid].h[0]; + h[1] = tmps[gid].h[1]; + h[2] = tmps[gid].h[2]; + h[3] = tmps[gid].h[3]; + h[4] = tmps[gid].h[4]; + h[5] = tmps[gid].h[5]; + h[6] = tmps[gid].h[6]; + h[7] = tmps[gid].h[7]; + + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; + + w0[0] = 0x80000000; + w0[1] = 0; + w0[2] = 0; + w0[3] = 0; + w1[0] = 0; + w1[1] = 0; + w1[2] = 0; + w1[3] = 0; + w2[0] = 0; + w2[1] = 0; + w2[2] = 0; + w2[3] = 0; + w3[0] = 0; + w3[1] = 0; + w3[2] = 0; + w3[3] = tmps[gid].len * 8; + + sha256_transform (w0, w1, w2, w3, h); + + hooks[gid].ukey[0] = hc_swap32_S (h[0]); + hooks[gid].ukey[1] = hc_swap32_S (h[1]); + hooks[gid].ukey[2] = hc_swap32_S (h[2]); + hooks[gid].ukey[3] = hc_swap32_S (h[3]); + hooks[gid].ukey[4] = hc_swap32_S (h[4]); + hooks[gid].ukey[5] = hc_swap32_S (h[5]); + hooks[gid].ukey[6] = hc_swap32_S (h[6]); + hooks[gid].ukey[7] = hc_swap32_S (h[7]); +} + +KERNEL_FQ void m11600_comp (KERN_ATTR_TMPS_HOOKS (seven_zip_tmp_t, seven_zip_hook_t)) +{ + /** + * base + */ + + const u64 gid = get_global_id (0); + + if (gid >= gid_max) return; + + if (hooks[gid].hook_success == 1) + { + if (atomic_inc (&hashes_shown[digests_offset]) == 0) + { + mark_hash (plains_buf, d_return_buf, salt_pos, digests_cnt, 0, digests_offset + 0, gid, 0, 0, 0); + } + + return; + } +} diff --git a/OpenCL/m11600-pure.cl b/OpenCL/m11600-pure.cl index 545a0545c..481deb161 100644 --- a/OpenCL/m11600-pure.cl +++ b/OpenCL/m11600-pure.cl @@ -289,46 +289,49 @@ KERNEL_FQ void m11600_hook23 (KERN_ATTR_TMPS_HOOKS (seven_zip_tmp_t, seven_zip_h * context load */ - sha256_ctx_t ctx; - - ctx.h[0] = tmps[gid].h[0]; - ctx.h[1] = tmps[gid].h[1]; - ctx.h[2] = tmps[gid].h[2]; - ctx.h[3] = tmps[gid].h[3]; - ctx.h[4] = tmps[gid].h[4]; - ctx.h[5] = tmps[gid].h[5]; - ctx.h[6] = tmps[gid].h[6]; - ctx.h[7] = tmps[gid].h[7]; - - ctx.w0[0] = tmps[gid].w0[0]; - ctx.w0[1] = tmps[gid].w0[1]; - ctx.w0[2] = tmps[gid].w0[2]; - ctx.w0[3] = tmps[gid].w0[3]; - ctx.w1[0] = tmps[gid].w1[0]; - ctx.w1[1] = tmps[gid].w1[1]; - ctx.w1[2] = tmps[gid].w1[2]; - ctx.w1[3] = tmps[gid].w1[3]; - ctx.w2[0] = tmps[gid].w2[0]; - ctx.w2[1] = tmps[gid].w2[1]; - ctx.w2[2] = tmps[gid].w2[2]; - ctx.w2[3] = tmps[gid].w2[3]; - ctx.w3[0] = tmps[gid].w3[0]; - ctx.w3[1] = tmps[gid].w3[1]; - ctx.w3[2] = tmps[gid].w3[2]; - ctx.w3[3] = tmps[gid].w3[3]; + u32 h[8]; - ctx.len = tmps[gid].len; + h[0] = tmps[gid].h[0]; + h[1] = tmps[gid].h[1]; + h[2] = tmps[gid].h[2]; + h[3] = tmps[gid].h[3]; + h[4] = tmps[gid].h[4]; + h[5] = tmps[gid].h[5]; + h[6] = tmps[gid].h[6]; + h[7] = tmps[gid].h[7]; - sha256_final (&ctx); + u32 w0[4]; + u32 w1[4]; + u32 w2[4]; + u32 w3[4]; - hooks[gid].ukey[0] = hc_swap32_S (ctx.h[0]); - hooks[gid].ukey[1] = hc_swap32_S (ctx.h[1]); - hooks[gid].ukey[2] = hc_swap32_S (ctx.h[2]); - hooks[gid].ukey[3] = hc_swap32_S (ctx.h[3]); - hooks[gid].ukey[4] = hc_swap32_S (ctx.h[4]); - hooks[gid].ukey[5] = hc_swap32_S (ctx.h[5]); - hooks[gid].ukey[6] = hc_swap32_S (ctx.h[6]); - hooks[gid].ukey[7] = hc_swap32_S (ctx.h[7]); + w0[0] = 0x80000000; + w0[1] = 0; + w0[2] = 0; + w0[3] = 0; + w1[0] = 0; + w1[1] = 0; + w1[2] = 0; + w1[3] = 0; + w2[0] = 0; + w2[1] = 0; + w2[2] = 0; + w2[3] = 0; + w3[0] = 0; + w3[1] = 0; + w3[2] = 0; + w3[3] = tmps[gid].len * 8; + + sha256_transform (w0, w1, w2, w3, h); + + hooks[gid].ukey[0] = hc_swap32_S (h[0]); + hooks[gid].ukey[1] = hc_swap32_S (h[1]); + hooks[gid].ukey[2] = hc_swap32_S (h[2]); + hooks[gid].ukey[3] = hc_swap32_S (h[3]); + hooks[gid].ukey[4] = hc_swap32_S (h[4]); + hooks[gid].ukey[5] = hc_swap32_S (h[5]); + hooks[gid].ukey[6] = hc_swap32_S (h[6]); + hooks[gid].ukey[7] = hc_swap32_S (h[7]); } KERNEL_FQ void m11600_comp (KERN_ATTR_TMPS_HOOKS (seven_zip_tmp_t, seven_zip_hook_t)) diff --git a/src/interface.c b/src/interface.c index 68be9f796..e514a1ca8 100644 --- a/src/interface.c +++ b/src/interface.c @@ -92,12 +92,6 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx) hashconfig->hlfmt_disable = default_hlfmt_disable (hashconfig, user_options, user_options_extra); hashconfig->hook_salt_size = default_hook_salt_size (hashconfig, user_options, user_options_extra); hashconfig->hook_size = default_hook_size (hashconfig, user_options, user_options_extra); - hashconfig->kernel_accel_min = default_kernel_accel_min (hashconfig, user_options, user_options_extra); - hashconfig->kernel_accel_max = default_kernel_accel_max (hashconfig, user_options, user_options_extra); - hashconfig->kernel_loops_min = default_kernel_loops_min (hashconfig, user_options, user_options_extra); - hashconfig->kernel_loops_max = default_kernel_loops_max (hashconfig, user_options, user_options_extra); - hashconfig->kernel_threads_min = default_kernel_threads_min (hashconfig, user_options, user_options_extra); - hashconfig->kernel_threads_max = default_kernel_threads_max (hashconfig, user_options, user_options_extra); hashconfig->outfile_check_disable = default_outfile_check_disable (hashconfig, user_options, user_options_extra); hashconfig->outfile_check_nocomp = default_outfile_check_nocomp (hashconfig, user_options, user_options_extra); hashconfig->potfile_disable = default_potfile_disable (hashconfig, user_options, user_options_extra); @@ -267,12 +261,6 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx) if (module_ctx->module_hlfmt_disable != MODULE_DEFAULT) hashconfig->hlfmt_disable = module_ctx->module_hlfmt_disable (hashconfig, user_options, user_options_extra); if (module_ctx->module_hook_salt_size != MODULE_DEFAULT) hashconfig->hook_salt_size = module_ctx->module_hook_salt_size (hashconfig, user_options, user_options_extra); if (module_ctx->module_hook_size != MODULE_DEFAULT) hashconfig->hook_size = module_ctx->module_hook_size (hashconfig, user_options, user_options_extra); - if (module_ctx->module_kernel_accel_min != MODULE_DEFAULT) hashconfig->kernel_accel_min = module_ctx->module_kernel_accel_min (hashconfig, user_options, user_options_extra); - if (module_ctx->module_kernel_accel_max != MODULE_DEFAULT) hashconfig->kernel_accel_max = module_ctx->module_kernel_accel_max (hashconfig, user_options, user_options_extra); - if (module_ctx->module_kernel_loops_min != MODULE_DEFAULT) hashconfig->kernel_loops_min = module_ctx->module_kernel_loops_min (hashconfig, user_options, user_options_extra); - if (module_ctx->module_kernel_loops_max != MODULE_DEFAULT) hashconfig->kernel_loops_max = module_ctx->module_kernel_loops_max (hashconfig, user_options, user_options_extra); - if (module_ctx->module_kernel_threads_min != MODULE_DEFAULT) hashconfig->kernel_threads_min = module_ctx->module_kernel_threads_min (hashconfig, user_options, user_options_extra); - if (module_ctx->module_kernel_threads_max != MODULE_DEFAULT) hashconfig->kernel_threads_max = module_ctx->module_kernel_threads_max (hashconfig, user_options, user_options_extra); if (module_ctx->module_outfile_check_disable != MODULE_DEFAULT) hashconfig->outfile_check_disable = module_ctx->module_outfile_check_disable (hashconfig, user_options, user_options_extra); if (module_ctx->module_outfile_check_nocomp != MODULE_DEFAULT) hashconfig->outfile_check_nocomp = module_ctx->module_outfile_check_nocomp (hashconfig, user_options, user_options_extra); if (module_ctx->module_potfile_disable != MODULE_DEFAULT) hashconfig->potfile_disable = module_ctx->module_potfile_disable (hashconfig, user_options, user_options_extra); @@ -416,15 +404,27 @@ int hashconfig_init (hashcat_ctx_t *hashcat_ctx) // those depend on some previously defined values - hashconfig->pw_max = default_pw_max (hashconfig, user_options, user_options_extra); - hashconfig->pw_min = default_pw_min (hashconfig, user_options, user_options_extra); - hashconfig->salt_max = default_salt_max (hashconfig, user_options, user_options_extra); - hashconfig->salt_min = default_salt_min (hashconfig, user_options, user_options_extra); - - if (module_ctx->module_pw_max != MODULE_DEFAULT) hashconfig->pw_max = module_ctx->module_pw_max (hashconfig, user_options, user_options_extra); - if (module_ctx->module_pw_min != MODULE_DEFAULT) hashconfig->pw_min = module_ctx->module_pw_min (hashconfig, user_options, user_options_extra); - if (module_ctx->module_salt_max != MODULE_DEFAULT) hashconfig->salt_max = module_ctx->module_salt_max (hashconfig, user_options, user_options_extra); - if (module_ctx->module_salt_min != MODULE_DEFAULT) hashconfig->salt_min = module_ctx->module_salt_min (hashconfig, user_options, user_options_extra); + hashconfig->pw_max = default_pw_max (hashconfig, user_options, user_options_extra); + hashconfig->pw_min = default_pw_min (hashconfig, user_options, user_options_extra); + hashconfig->salt_max = default_salt_max (hashconfig, user_options, user_options_extra); + hashconfig->salt_min = default_salt_min (hashconfig, user_options, user_options_extra); + hashconfig->kernel_accel_min = default_kernel_accel_min (hashconfig, user_options, user_options_extra); + hashconfig->kernel_accel_max = default_kernel_accel_max (hashconfig, user_options, user_options_extra); + hashconfig->kernel_loops_min = default_kernel_loops_min (hashconfig, user_options, user_options_extra); + hashconfig->kernel_loops_max = default_kernel_loops_max (hashconfig, user_options, user_options_extra); + hashconfig->kernel_threads_min = default_kernel_threads_min (hashconfig, user_options, user_options_extra); + hashconfig->kernel_threads_max = default_kernel_threads_max (hashconfig, user_options, user_options_extra); + + if (module_ctx->module_pw_max != MODULE_DEFAULT) hashconfig->pw_max = module_ctx->module_pw_max (hashconfig, user_options, user_options_extra); + if (module_ctx->module_pw_min != MODULE_DEFAULT) hashconfig->pw_min = module_ctx->module_pw_min (hashconfig, user_options, user_options_extra); + if (module_ctx->module_salt_max != MODULE_DEFAULT) hashconfig->salt_max = module_ctx->module_salt_max (hashconfig, user_options, user_options_extra); + if (module_ctx->module_salt_min != MODULE_DEFAULT) hashconfig->salt_min = module_ctx->module_salt_min (hashconfig, user_options, user_options_extra); + if (module_ctx->module_kernel_accel_min != MODULE_DEFAULT) hashconfig->kernel_accel_min = module_ctx->module_kernel_accel_min (hashconfig, user_options, user_options_extra); + if (module_ctx->module_kernel_accel_max != MODULE_DEFAULT) hashconfig->kernel_accel_max = module_ctx->module_kernel_accel_max (hashconfig, user_options, user_options_extra); + if (module_ctx->module_kernel_loops_min != MODULE_DEFAULT) hashconfig->kernel_loops_min = module_ctx->module_kernel_loops_min (hashconfig, user_options, user_options_extra); + if (module_ctx->module_kernel_loops_max != MODULE_DEFAULT) hashconfig->kernel_loops_max = module_ctx->module_kernel_loops_max (hashconfig, user_options, user_options_extra); + if (module_ctx->module_kernel_threads_min != MODULE_DEFAULT) hashconfig->kernel_threads_min = module_ctx->module_kernel_threads_min (hashconfig, user_options, user_options_extra); + if (module_ctx->module_kernel_threads_max != MODULE_DEFAULT) hashconfig->kernel_threads_max = module_ctx->module_kernel_threads_max (hashconfig, user_options, user_options_extra); return 0; } diff --git a/src/modules/module_11600.c b/src/modules/module_11600.c index ae556b6c2..1a8a9b033 100644 --- a/src/modules/module_11600.c +++ b/src/modules/module_11600.c @@ -307,14 +307,46 @@ u32 module_kernel_accel_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_ u32 module_pw_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) { - // this overrides the reductions of PW_MAX in case optimized kernel is selected - // IOW, even in optimized kernel mode it support length 256 + const bool optimized_kernel = (hashconfig->opti_type & OPTI_TYPE_OPTIMIZED_KERNEL); - const u32 pw_max = PW_MAX; + u32 pw_max = PW_MAX; + + if (optimized_kernel == true) + { + pw_max = 20; + } return pw_max; } +u32 module_kernel_loops_min (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) +{ + const bool optimized_kernel = (hashconfig->opti_type & OPTI_TYPE_OPTIMIZED_KERNEL); + + u32 kernel_loops_min = KERNEL_LOOPS_MIN; + + if (optimized_kernel == true) + { + kernel_loops_min = 4096; + } + + return kernel_loops_min; +} + +u32 module_kernel_loops_max (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra) +{ + const bool optimized_kernel = (hashconfig->opti_type & OPTI_TYPE_OPTIMIZED_KERNEL); + + u32 kernel_loops_max = KERNEL_LOOPS_MAX; + + if (optimized_kernel == true) + { + kernel_loops_max = 4096; + } + + return kernel_loops_max; +} + char *module_jit_build_options (MAYBE_UNUSED const hashconfig_t *hashconfig, MAYBE_UNUSED const user_options_t *user_options, MAYBE_UNUSED const user_options_extra_t *user_options_extra, MAYBE_UNUSED const hashes_t *hashes, MAYBE_UNUSED const hc_device_param_t *device_param) { char *jit_build_options = NULL; @@ -740,8 +772,8 @@ void module_init (module_ctx_t *module_ctx) module_ctx->module_jit_cache_disable = MODULE_DEFAULT; module_ctx->module_kernel_accel_max = module_kernel_accel_max; module_ctx->module_kernel_accel_min = MODULE_DEFAULT; - module_ctx->module_kernel_loops_max = MODULE_DEFAULT; - module_ctx->module_kernel_loops_min = MODULE_DEFAULT; + module_ctx->module_kernel_loops_max = module_kernel_loops_max; + module_ctx->module_kernel_loops_min = module_kernel_loops_min; module_ctx->module_kernel_threads_max = MODULE_DEFAULT; module_ctx->module_kernel_threads_min = MODULE_DEFAULT; module_ctx->module_kern_type = module_kern_type; diff --git a/tools/test_modules/m11600.pm b/tools/test_modules/m11600.pm index 1bdf02efe..195a04e88 100644 --- a/tools/test_modules/m11600.pm +++ b/tools/test_modules/m11600.pm @@ -13,7 +13,7 @@ use Digest::CRC qw (crc32); use Digest::SHA qw (sha256); use Encode; -sub module_constraints { [[0, 256], [0, 16], [-1, -1], [-1, -1], [-1, -1]] } +sub module_constraints { [[0, 256], [0, 16], [0, 20], [0, 16], [-1, -1]] } sub module_generate_hash {