libgpuverify

Signature verification on GPUs (WiP)
Log | Files | Refs | README | LICENSE

commit 6de36dce671c293d9b3471bbfbd9c5b5242a03f7
parent 5ae7582d89b9e556c0b6c80fc3e023bdb5380c17
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed, 17 Jan 2024 13:38:31 +0100

more hints

Diffstat:
MREADME.md | 9+++++++--
Msource/util.c | 775+++++++++++++++++++++++++++++++++++++++++++------------------------------------
2 files changed, 428 insertions(+), 356 deletions(-)

diff --git a/README.md b/README.md @@ -16,7 +16,12 @@ libgcrypt is required for cryptographic operations: https://www.gnupg.org/software/libgcrypt/index.html The gmp library is required for calculations on very large integers: -apt install libgmp3-dev +# apt install libgmp3-dev OpenCL drivers & headers: -apt install ocl-icd-opencl-dev +# apt install ocl-icd-opencl-dev + +For Nvidia, you also need to: + +# apt install nvidia-opencl-icd + diff --git a/source/util.c b/source/util.c @@ -18,52 +18,58 @@ #include "util.h" -unsigned long gpuvt_estimate_pairs(void) { - - struct stat ss; - - int msfile = open("../lib-gpu-generate/msgsig.txt", O_RDONLY); - - if (-1 == msfile) - { - fprintf (stderr, - "Failed to open: err %s\n", - strerror (errno)); - exit (1); - } - - fstat(msfile, &ss); - - unsigned long len_f = ss.st_size; - unsigned long len_sig = (GPUV_BIT_LENGTH_2048 / 8) * 2 + 1; // this is the size of a 2048 bit signature in the file - - unsigned long n_min = len_f / (len_sig + 3); // if each message was only one character, then this would be the maximum amount of signatures that could be in the file – use this estimate to allocate storage for the signatures - - close(msfile); - - return n_min == 0 ? 1 : n_min; +unsigned long +gpuvt_estimate_pairs (void) +{ + + struct stat ss; + + int msfile = open ("../lib-gpu-generate/msgsig.txt", O_RDONLY); + + if (-1 == msfile) + { + fprintf (stderr, + "Failed to open: err %s\n", + strerror (errno)); + exit (1); + } + + fstat (msfile, &ss); + + unsigned long len_f = ss.st_size; + unsigned long len_sig = (GPUV_BIT_LENGTH_2048 / 8) * 2 + 1; // this is the size of a 2048 bit signature in the file + + unsigned long n_min = len_f / (len_sig + 3); // if each message was only one character, then this would be the maximum amount of signatures that could be in the file – use this estimate to allocate storage for the signatures + + close (msfile); + + return n_min == 0 ? 1 : n_min; } -void gpuv_prepare_gcry(void) { +void +gpuv_prepare_gcry (void) +{ - /* Version check should be the very first call because it - makes sure that important subsystems are initialized. - #define NEED_LIBGCRYPT_VERSION to the minimum required version. */ - if (!gcry_check_version (NEED_LIBGCRYPT_VERSION)) - { - fprintf (stderr, "libgcrypt is too old (need %s, have %s)\n", - NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL)); - exit (2); } - /* Disable secure memory. */ - gcry_control (GCRYCTL_DISABLE_SECMEM, 0); - /* ... If required, other initialization goes here. */ - /* Tell Libgcrypt that initialization has completed. */ - gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + /* Version check should be the very first call because it + makes sure that important subsystems are initialized. + #define NEED_LIBGCRYPT_VERSION to the minimum required version. */ + if (! gcry_check_version (NEED_LIBGCRYPT_VERSION)) + { + fprintf (stderr, "libgcrypt is too old (need %s, have %s)\n", + NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL)); + exit (2); + } + /* Disable secure memory. */ + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + /* ... If required, other initialization goes here. */ + /* Tell Libgcrypt that initialization has completed. */ + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); } + cl_platform_id select_platform (unsigned int offset, bool print_platforms) @@ -79,7 +85,7 @@ select_platform (unsigned int offset, if (CL_SUCCESS != rplat) { fprintf (stderr, - "Error: Failed to lookup platforms! (%d)\n", + "Error: Failed to lookup platforms! Maybe install $VENDOR-opencl-icd package? (Error #%d)\n", rplat); exit (1); } @@ -194,6 +200,7 @@ select_device (cl_platform_id platform) return device_id; } + void logger (const char *errinfo, const void *private_info, @@ -205,6 +212,7 @@ logger (const char *errinfo, errinfo); } + cl_context create_compute_context (cl_device_id device_id) { @@ -226,6 +234,7 @@ create_compute_context (cl_device_id device_id) return context; } + cl_command_queue create_command_queue (cl_device_id device_id, cl_context context) @@ -247,6 +256,7 @@ create_command_queue (cl_device_id device_id, return commands; } + cl_program compile_program (cl_device_id device_id, cl_context context, @@ -341,6 +351,7 @@ compile_program (cl_device_id device_id, return program; } + cl_kernel create_kernel (cl_program program, const char *name) @@ -362,350 +373,406 @@ create_kernel (cl_program program, return kernel; } + // implementations of functions used by universal, but they themselves should not be exposed /* called after results has been copied from the gpu. releases many of the state variables, and invalidates the object calls the users closure */ -void CL_CALLBACK callback_result(cl_event event, cl_int event_command_status, void *user_data) { - - //clReleaseEvent(event); - - struct gpuv_state *state = (struct gpuv_state *)user_data; - - // finish calculating results, and release memory - - clReleaseMemObject(state->x_mem); - clReleaseMemObject(state->m_mem); - clReleaseMemObject(state->n_mem); - clReleaseMemObject(state->ni_mem); - clReleaseMemObject(state->exp_mem); - clReleaseMemObject(state->msg_mem); - clReleaseMemObject(state->pks_indices); - - clReleaseCommandQueue(state->queue); - - state->stale = 1; - - struct timespec p1 = state->t; - - clock_gettime(CLOCK_REALTIME, &state->t); - - state->t.tv_sec = ( state->t.tv_nsec < p1.tv_nsec ? state->t.tv_sec - (p1.tv_sec + 1) : state->t.tv_sec - p1.tv_sec ); - state->t.tv_nsec = ( state->t.tv_nsec < p1.tv_nsec ? ((999999999 - p1.tv_nsec) + state->t.tv_nsec) : (state->t.tv_nsec - p1.tv_nsec) ) / 1000; - - // the user could check this themselves, but I give them a boolean field valid, that says whether there is a faulty signature in the batch or not - - int ret = 1; - - unsigned long partial = state->sig_count / (sizeof(uint32_t) * 8); - - for(int i = 0; i < state->results_len; i++) { - - uint32_t mask = 0; - - if (i >= partial) { - int remaining = state->sig_count % (sizeof(uint32_t) * 8); - - for (int x = 0; x < remaining; x++) { mask |= 1 << x; } - - } else { - mask = UINT32_MAX; - } - - if (state->results[i] != mask) { - ret = 0; - } +void CL_CALLBACK +callback_result (cl_event event, cl_int event_command_status, void *user_data) +{ + + // clReleaseEvent(event); + + struct gpuv_state *state = (struct gpuv_state *) user_data; + + // finish calculating results, and release memory + + clReleaseMemObject (state->x_mem); + clReleaseMemObject (state->m_mem); + clReleaseMemObject (state->n_mem); + clReleaseMemObject (state->ni_mem); + clReleaseMemObject (state->exp_mem); + clReleaseMemObject (state->msg_mem); + clReleaseMemObject (state->pks_indices); + + clReleaseCommandQueue (state->queue); + + state->stale = 1; + + struct timespec p1 = state->t; + + clock_gettime (CLOCK_REALTIME, &state->t); + + state->t.tv_sec = (state->t.tv_nsec < p1.tv_nsec ? state->t.tv_sec + - (p1.tv_sec + 1) : state->t.tv_sec - p1.tv_sec); + state->t.tv_nsec = (state->t.tv_nsec < p1.tv_nsec ? ((999999999 + - p1.tv_nsec) + + state->t.tv_nsec) : + (state->t.tv_nsec - p1.tv_nsec) ) / 1000; + + // the user could check this themselves, but I give them a boolean field valid, that says whether there is a faulty signature in the batch or not + + int ret = 1; + + unsigned long partial = state->sig_count / (sizeof(uint32_t) * 8); + + for (int i = 0; i < state->results_len; i++) + { + + uint32_t mask = 0; + + if (i >= partial) + { + int remaining = state->sig_count % (sizeof(uint32_t) * 8); + + for (int x = 0; x < remaining; x++) + { + mask |= 1 << x; + } + } - - state->info->in_progress = 0; - state->valid = ret; - - // pass results to user - state->cls(state->arg, state->valid, state->t, state->results_len, state->results); - + else + { + mask = UINT32_MAX; + } + + if (state->results[i] != mask) + { + ret = 0; + } + } + + state->info->in_progress = 0; + state->valid = ret; + + // pass results to user + state->cls (state->arg, state->valid, state->t, state->results_len, + state->results); + } + /* called after kernel finishes. launches another async process to copy the results from gpu memory */ -void CL_CALLBACK callback_kernel(cl_event event, cl_int event_command_status, void *user_data) { - - //clReleaseEvent(event); // only call here if we wait for completion - - struct gpuv_state *state = (struct gpuv_state *)user_data; - - //MARK: no expensive operations here - - unsigned long res_len = state->results_len; - unsigned long res_len_bytes = res_len * sizeof(uint32_t); - - int err = 0; - - cl_event e = clCreateUserEvent(state->info->context, NULL); - - // Read back the results from the device to verify the output - err = clEnqueueReadBuffer(state->queue, state->res_mem, CL_TRUE, 0, res_len_bytes, state->results, 0, NULL, &e); - if (err != CL_SUCCESS) - { - printf("Error: Failed to read output array! %d\n", err); - exit(1); - } - - clSetEventCallback(e, CL_COMPLETE, callback_result, state); - clReleaseEvent(e); -} +void CL_CALLBACK +callback_kernel (cl_event event, cl_int event_command_status, void *user_data) +{ + + // clReleaseEvent(event); // only call here if we wait for completion + + struct gpuv_state *state = (struct gpuv_state *) user_data; + + // MARK: no expensive operations here + + unsigned long res_len = state->results_len; + unsigned long res_len_bytes = res_len * sizeof(uint32_t); + + int err = 0; + + cl_event e = clCreateUserEvent (state->info->context, NULL); + + // Read back the results from the device to verify the output + err = clEnqueueReadBuffer (state->queue, state->res_mem, CL_TRUE, 0, + res_len_bytes, state->results, 0, NULL, &e); + if (err != CL_SUCCESS) + { + printf ("Error: Failed to read output array! %d\n", err); + exit (1); + } + clSetEventCallback (e, CL_COMPLETE, callback_result, state); + clReleaseEvent (e); +} #define ORDER -1 // I think we need to do this, because we want to write it in the 'wrong' way #define END 0 -//#define GPUV_BIT_LENGTH 2048 +// #define GPUV_BIT_LENGTH 2048 #define BITS 64 -void pk_to_mont(struct gpuv_public_key * pk) { - - if (pk->prepared) return; - - gpu_register *ni_buf = malloc(pk->len_n * sizeof(gpu_register)); - memset(ni_buf, 0, pk->len_n * sizeof(gpu_register)); - gpu_register *r_1_buf = malloc(pk->len_n * sizeof(gpu_register)); - memset(r_1_buf, 0, pk->len_n * sizeof(gpu_register)); - - mpz_t mod, r, r_1, ni; - - mpz_init(r); - mpz_init(r_1); - mpz_init(ni); - mpz_init(mod); - - mpz_t one; // helper variable - mpz_init_set_si(one,1); - - mpz_set_si(one, 1); - mpz_mul_2exp(r,one,GPUV_BIT_LENGTH_2048); // r - - mpz_import(mod, pk->len_n, ORDER, sizeof(gpu_register), END, 0, pk->n); - - mpz_gcdext(one, r_1, ni, r, mod); // set r_1 and ni - - int sgn = mpz_sgn(r_1); - - mpz_abs(r_1, r_1); - mpz_abs(ni, ni); - - if (sgn == -1) { - mpz_sub(ni, r, ni); - mpz_sub(r_1, mod, r_1); - } - - mpz_export(ni_buf, NULL, ORDER, sizeof(gpu_register), END, 0, ni); - mpz_export(r_1_buf, NULL, ORDER, sizeof(gpu_register), END, 0, r_1); - - pk->ni = (char *)ni_buf; - pk->len_ni = pk->len_n; // has to be the same length as n - pk->r_1 = (char *)r_1_buf; - pk->len_r_1 = pk->len_n; - - mpz_clear(r); - mpz_clear(r_1); - mpz_clear(ni); - mpz_clear(one); - mpz_clear(mod); - - pk->prepared = 1; - +void +pk_to_mont (struct gpuv_public_key *pk) +{ + + if (pk->prepared) + return; + + gpu_register *ni_buf = malloc (pk->len_n * sizeof(gpu_register)); + memset (ni_buf, 0, pk->len_n * sizeof(gpu_register)); + gpu_register *r_1_buf = malloc (pk->len_n * sizeof(gpu_register)); + memset (r_1_buf, 0, pk->len_n * sizeof(gpu_register)); + + mpz_t mod, r, r_1, ni; + + mpz_init (r); + mpz_init (r_1); + mpz_init (ni); + mpz_init (mod); + + mpz_t one; // helper variable + mpz_init_set_si (one,1); + + mpz_set_si (one, 1); + mpz_mul_2exp (r,one,GPUV_BIT_LENGTH_2048); // r + + mpz_import (mod, pk->len_n, ORDER, sizeof(gpu_register), END, 0, pk->n); + + mpz_gcdext (one, r_1, ni, r, mod); // set r_1 and ni + + int sgn = mpz_sgn (r_1); + + mpz_abs (r_1, r_1); + mpz_abs (ni, ni); + + if (sgn == -1) + { + mpz_sub (ni, r, ni); + mpz_sub (r_1, mod, r_1); + } + + mpz_export (ni_buf, NULL, ORDER, sizeof(gpu_register), END, 0, ni); + mpz_export (r_1_buf, NULL, ORDER, sizeof(gpu_register), END, 0, r_1); + + pk->ni = (char *) ni_buf; + pk->len_ni = pk->len_n; // has to be the same length as n + pk->r_1 = (char *) r_1_buf; + pk->len_r_1 = pk->len_n; + + mpz_clear (r); + mpz_clear (r_1); + mpz_clear (ni); + mpz_clear (one); + mpz_clear (mod); + + pk->prepared = 1; + } -void sig_msg_to_mont(struct gpuv_signature_message * sig_msg) { - - if (sig_msg->prepared) - { - - return; - } - - gpu_register *x_buf = malloc(sig_msg->pubkey->len_n * sizeof(gpu_register)); - memset(x_buf, 0, sig_msg->pubkey->len_n * sizeof(gpu_register)); - gpu_register *M_buf = malloc(sig_msg->pubkey->len_n * sizeof(gpu_register)); - memset(M_buf, 0, sig_msg->pubkey->len_n * sizeof(gpu_register)); - - - mpz_t mod, sig; - mpz_init(sig); - mpz_init(mod); - - mpz_t M, x, r; - - mpz_init(M); - mpz_init(x); - mpz_init(r); - - mpz_t one; // helper variable - mpz_init_set_si(one,1); - - mpz_set_si(one, 1); - mpz_mul_2exp(r,one,GPUV_BIT_LENGTH_2048); // r - - mpz_import(mod, sig_msg->pubkey->len_n, ORDER, sizeof(gpu_register), END, 0, sig_msg->pubkey->n); - - mpz_import(sig, sig_msg->len_s, ORDER, sizeof(gpu_register), END, 0, sig_msg->s); - - // set x (the number to 'square' (multiply by itself)) - mpz_mul(M, sig, r); - mpz_mod(M, M, mod); - - mpz_mod(x, r, mod); - - mpz_export(x_buf, NULL, ORDER, sizeof(gpu_register), END, 0, x); - mpz_export(M_buf, NULL, ORDER, sizeof(gpu_register), END, 0, M); - - mpz_clear(sig); - mpz_clear(mod); - mpz_clear(r); - mpz_clear(one); - mpz_clear(M); - mpz_clear(x); - - sig_msg->x = (char *)x_buf; - sig_msg->len_x = sig_msg->pubkey->len_n; - sig_msg->M = (char *)M_buf; - sig_msg->len_M = sig_msg->pubkey->len_n; - - sig_msg->prepared = 1; - + +void +sig_msg_to_mont (struct gpuv_signature_message *sig_msg) +{ + + if (sig_msg->prepared) + { + + return; + } + + gpu_register *x_buf = malloc (sig_msg->pubkey->len_n * sizeof(gpu_register)); + memset (x_buf, 0, sig_msg->pubkey->len_n * sizeof(gpu_register)); + gpu_register *M_buf = malloc (sig_msg->pubkey->len_n * sizeof(gpu_register)); + memset (M_buf, 0, sig_msg->pubkey->len_n * sizeof(gpu_register)); + + + mpz_t mod, sig; + mpz_init (sig); + mpz_init (mod); + + mpz_t M, x, r; + + mpz_init (M); + mpz_init (x); + mpz_init (r); + + mpz_t one; // helper variable + mpz_init_set_si (one,1); + + mpz_set_si (one, 1); + mpz_mul_2exp (r,one,GPUV_BIT_LENGTH_2048); // r + + mpz_import (mod, sig_msg->pubkey->len_n, ORDER, sizeof(gpu_register), END, 0, + sig_msg->pubkey->n); + + mpz_import (sig, sig_msg->len_s, ORDER, sizeof(gpu_register), END, 0, + sig_msg->s); + + // set x (the number to 'square' (multiply by itself)) + mpz_mul (M, sig, r); + mpz_mod (M, M, mod); + + mpz_mod (x, r, mod); + + mpz_export (x_buf, NULL, ORDER, sizeof(gpu_register), END, 0, x); + mpz_export (M_buf, NULL, ORDER, sizeof(gpu_register), END, 0, M); + + mpz_clear (sig); + mpz_clear (mod); + mpz_clear (r); + mpz_clear (one); + mpz_clear (M); + mpz_clear (x); + + sig_msg->x = (char *) x_buf; + sig_msg->len_x = sig_msg->pubkey->len_n; + sig_msg->M = (char *) M_buf; + sig_msg->len_M = sig_msg->pubkey->len_n; + + sig_msg->prepared = 1; + } -gcry_sexp_t *sexp_from_string(char* str, const char *format) { - - gcry_sexp_t *sexp = malloc(sizeof(gcry_sexp_t)); - - gcry_mpi_t mpi; - - char * str_buf = malloc((GPUV_BIT_LENGTH_2048 / 8) * 2 + 8); - - mpz_t m; - mpz_init(m); - - mpz_import(m, 32, ORDER, sizeof(gpu_register), END, 0, str); - - mpz_get_str(str_buf, 16, m); - - - gcry_mpi_scan(&mpi, GCRYMPI_FMT_HEX, str_buf, 0, NULL); - - size_t errOff = 0; - gcry_sexp_build(sexp,&errOff,format,mpi); - - gcry_mpi_release(mpi); - free(str_buf); - - mpz_clear(m); - - return sexp; + +gcry_sexp_t * +sexp_from_string (char*str, const char *format) +{ + + gcry_sexp_t *sexp = malloc (sizeof(gcry_sexp_t)); + + gcry_mpi_t mpi; + + char *str_buf = malloc ((GPUV_BIT_LENGTH_2048 / 8) * 2 + 8); + + mpz_t m; + mpz_init (m); + + mpz_import (m, 32, ORDER, sizeof(gpu_register), END, 0, str); + + mpz_get_str (str_buf, 16, m); + + + gcry_mpi_scan (&mpi, GCRYMPI_FMT_HEX, str_buf, 0, NULL); + + size_t errOff = 0; + gcry_sexp_build (sexp,&errOff,format,mpi); + + gcry_mpi_release (mpi); + free (str_buf); + + mpz_clear (m); + + return sexp; } -gcry_sexp_t *sexp_from_string_key(char* str_1, char* str_1_buf, unsigned long str_2, const char *format) { - - gcry_sexp_t *sexp = malloc(sizeof(gcry_sexp_t)); - - gcry_mpi_t mpi_1; - - - mpz_t m; - mpz_init(m); - - mpz_import(m, 32, ORDER, sizeof(gpu_register), END, 0, str_1); - - mpz_get_str(str_1_buf, 16, m); - - gcry_mpi_scan(&mpi_1, GCRYMPI_FMT_HEX, str_1_buf, 0, NULL); - - gcry_mpi_t mpi_2 = gcry_mpi_set_ui(NULL, str_2); - - size_t errOff = 0; - gcry_sexp_build(sexp,&errOff,format,mpi_1,mpi_2); - - gcry_mpi_release(mpi_1); - gcry_mpi_release(mpi_2); - - mpz_clear(m); - - return sexp; + +gcry_sexp_t * +sexp_from_string_key (char*str_1, char*str_1_buf, unsigned long str_2, const + char *format) +{ + + gcry_sexp_t *sexp = malloc (sizeof(gcry_sexp_t)); + + gcry_mpi_t mpi_1; + + + mpz_t m; + mpz_init (m); + + mpz_import (m, 32, ORDER, sizeof(gpu_register), END, 0, str_1); + + mpz_get_str (str_1_buf, 16, m); + + gcry_mpi_scan (&mpi_1, GCRYMPI_FMT_HEX, str_1_buf, 0, NULL); + + gcry_mpi_t mpi_2 = gcry_mpi_set_ui (NULL, str_2); + + size_t errOff = 0; + gcry_sexp_build (sexp,&errOff,format,mpi_1,mpi_2); + + gcry_mpi_release (mpi_1); + gcry_mpi_release (mpi_2); + + mpz_clear (m); + + return sexp; } -void cpu_verify(struct gpuv_batch *batch, struct gpuv_state *state) { - - struct timespec p1, p2; - - clock_gettime(CLOCK_REALTIME, &p1); - - for (int j = 0; j < batch->current; j++) { - - struct gpuv_public_key * p = batch->pairs[ j ].pubkey; - - char * str_key_buf = malloc((GPUV_BIT_LENGTH_2048 / 8) * 2 + 8); - - gcry_sexp_t * key_sexp = sexp_from_string_key(p->n, str_key_buf, p->e, "(public-key (rsa (n %m) (e %m)))" ); // pub key data - - gcry_sexp_t *m_sexp = sexp_from_string(batch->pairs[j].m, "(data (flags raw) (value %m))"); // message format (for comparison) - - gcry_sexp_t *s_sexp = sexp_from_string(batch->pairs[j].s, "(sig-val (rsa (s %m)))"); // signature format - - if ( gcry_pk_verify(*s_sexp, *m_sexp, *key_sexp) == 0 ) { - - uint32_t out_offset = j / (sizeof(uint32_t) * 8); // 32 bit - - uint32_t mv = 1 << j; - - state->results[out_offset] |= mv; - - } - - gcry_sexp_release(*m_sexp); - gcry_sexp_release(*s_sexp); - gcry_sexp_release(*key_sexp); - - free(str_key_buf); - + +void +cpu_verify (struct gpuv_batch *batch, struct gpuv_state *state) +{ + + struct timespec p1, p2; + + clock_gettime (CLOCK_REALTIME, &p1); + + for (int j = 0; j < batch->current; j++) + { + + struct gpuv_public_key *p = batch->pairs[ j ].pubkey; + + char *str_key_buf = malloc ((GPUV_BIT_LENGTH_2048 / 8) * 2 + 8); + + gcry_sexp_t *key_sexp = sexp_from_string_key (p->n, str_key_buf, p->e, + "(public-key (rsa (n %m) (e %m)))"); // pub key data + + gcry_sexp_t *m_sexp = sexp_from_string (batch->pairs[j].m, + "(data (flags raw) (value %m))"); // message format (for comparison) + + gcry_sexp_t *s_sexp = sexp_from_string (batch->pairs[j].s, + "(sig-val (rsa (s %m)))"); // signature format + + if (gcry_pk_verify (*s_sexp, *m_sexp, *key_sexp) == 0) + { + + uint32_t out_offset = j / (sizeof(uint32_t) * 8); // 32 bit + + uint32_t mv = 1 << j; + + state->results[out_offset] |= mv; + } - - state->stale = 1; - - int ret = 1; - - unsigned long partial = state->sig_count / (sizeof(uint32_t) * 8); - - for(int i = 0; i < state->results_len; i++) { - - uint32_t mask = 0; - - if (i >= partial) { - int remaining = state->sig_count % (sizeof(uint32_t) * 8); - - for (int x = 0; x < remaining; x++) { mask |= 1 << x; } - - } else { - mask = UINT32_MAX; - } - - if (state->results[i] != mask) { - ret = 0; - } + + gcry_sexp_release (*m_sexp); + gcry_sexp_release (*s_sexp); + gcry_sexp_release (*key_sexp); + + free (str_key_buf); + + } + + state->stale = 1; + + int ret = 1; + + unsigned long partial = state->sig_count / (sizeof(uint32_t) * 8); + + for (int i = 0; i < state->results_len; i++) + { + + uint32_t mask = 0; + + if (i >= partial) + { + int remaining = state->sig_count % (sizeof(uint32_t) * 8); + + for (int x = 0; x < remaining; x++) + { + mask |= 1 << x; + } + + } + else + { + mask = UINT32_MAX; + } + + if (state->results[i] != mask) + { + ret = 0; } - - state->info->in_progress = 0; - state->valid = ret; - - clock_gettime(CLOCK_REALTIME, &p2); - - state->t.tv_sec = ( p2.tv_nsec < p1.tv_nsec ? p2.tv_sec - (p1.tv_sec + 1) : p2.tv_sec - p1.tv_sec ); - state->t.tv_nsec = ( p2.tv_nsec < p1.tv_nsec ? ((999999999 - p1.tv_nsec) + p2.tv_nsec) : (p2.tv_nsec - p1.tv_nsec) ) / 1000; - - // pass results to user - state->cls(state->arg, state->valid, state->t, state->results_len, state->results); - + } + + state->info->in_progress = 0; + state->valid = ret; + + clock_gettime (CLOCK_REALTIME, &p2); + + state->t.tv_sec = (p2.tv_nsec < p1.tv_nsec ? p2.tv_sec - (p1.tv_sec + 1) : + p2.tv_sec - p1.tv_sec); + state->t.tv_nsec = (p2.tv_nsec < p1.tv_nsec ? ((999999999 - p1.tv_nsec) + + p2.tv_nsec) : (p2.tv_nsec + - p1.tv_nsec) ) + / 1000; + + // pass results to user + state->cls (state->arg, state->valid, state->t, state->results_len, + state->results); + }