From edd5d30b4ca0ef0d984896ed6dd2156d5e57d1aa Mon Sep 17 00:00:00 2001 From: wiire-a Date: Thu, 16 Nov 2017 14:38:45 +0100 Subject: [PATCH] Added another simpler glibc PRNG With these changes I was able to get a 9% increase in speed on my laptop. --- src/glibc_random.c | 68 ----------------------------- src/pixiewps.c | 22 +++++----- src/random/glibc_random.c | 58 ++++++++++++++++++++++++ src/random/glibc_random_lazy.c | 51 ++++++++++++++++++++++ src/{ => random}/glibc_random_old.c | 6 +-- 5 files changed, 122 insertions(+), 83 deletions(-) delete mode 100644 src/glibc_random.c create mode 100644 src/random/glibc_random.c create mode 100644 src/random/glibc_random_lazy.c rename src/{ => random}/glibc_random_old.c (95%) diff --git a/src/glibc_random.c b/src/glibc_random.c deleted file mode 100644 index aeb5be0..0000000 --- a/src/glibc_random.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * pixiewps: offline WPS brute-force utility that exploits low entropy PRNGs - * - * Copyright (c) 2015-2017, wiire - * SPDX-License-Identifier: GPL-3.0+ - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define GLIBC_PRNG_SIZE 344 -#define GLIBC_FAST_MAX_GEN 3 - -#if GLIBC_MAX_GEN < GLIBC_FAST_MAX_GEN - #error "GLIBC_MAX_GEN must be >= GLIBC_FAST_MAX_GEN" -#endif - -/* - * The +1 is used to keep the index inside the array after the increment, - * it doesn't really have a purpose besides that - */ -struct glibc_prng { - int index; - int state[GLIBC_PRNG_SIZE + GLIBC_MAX_GEN - GLIBC_FAST_MAX_GEN + 1]; -}; - -/* - * If only 3 numbers are generated then there's no need to store new values - */ -unsigned int glibc_rand_fast(struct glibc_prng *prng) -{ - const int *state = prng->state; - const int i = prng->index++; - return ((unsigned int)(state[i - 31] + state[i - 3])) >> 1; -} - -/* - * There are no checks of bounds (GLIBC_MAX_GEN is the maximum number of times it can be called) - */ -unsigned int glibc_rand(struct glibc_prng *prng) -{ - int *state = prng->state; - const int i = prng->index++; - state[i] = state[i - 31] + state[i - 3]; - return (unsigned int)state[i] >> 1; -} - -void glibc_seed(struct glibc_prng *prng, int seed) -{ - int i; - int *state = prng->state; - prng->index = GLIBC_PRNG_SIZE; - state[0] = seed; - for (i = 1; i < 31; i++) { - state[i] = (16807LL * state[i - 1]) % 2147483647; - if (state[i] < 0) - state[i] += 2147483647; - } - for (i = 31; i < 34; i++) state[i] = state[i - 31]; - for (i = 34; i < 344; i++) state[i] = state[i - 31] + state[i - 3]; -} diff --git a/src/pixiewps.c b/src/pixiewps.c index c8ecdf1..d5b0f38 100644 --- a/src/pixiewps.c +++ b/src/pixiewps.c @@ -42,7 +42,8 @@ #include "version.h" #define GLIBC_MAX_GEN 4 -#include "glibc_random.c" +#include "random/glibc_random.c" +#include "random/glibc_random_lazy.c" uint32_t ecos_rand_simplest(uint32_t *seed); uint32_t ecos_rand_simple(uint32_t *seed); @@ -92,23 +93,20 @@ static struct job_control { } job_control; static void *crack_thread(void *arg) { - struct glibc_prng glibc_prng; + struct glibc_lazyprng glibc_lazyprng; struct crack_job *j = arg; uint32_t seed = j->start; uint32_t limit = job_control.end; + uint32_t tmp[4]; while (!job_control.nonce_seed) { unsigned int i; - glibc_seed(&glibc_prng, seed); - for (i = 0; i < GLIBC_FAST_MAX_GEN; i++) { - const unsigned int res = glibc_rand_fast(&glibc_prng); - if (res != job_control.randr_enonce[i]) - break; - } - - if (i == GLIBC_FAST_MAX_GEN) { - job_control.nonce_seed = seed; - DEBUG_PRINT("Seed found %u", seed); + glibc_lazyseed(&glibc_lazyprng, seed); + if (glibc_rand1(&glibc_lazyprng) == job_control.randr_enonce[0]) { + if (!memcmp(glibc_randfill(&glibc_lazyprng, tmp), job_control.randr_enonce, 4)) { + job_control.nonce_seed = seed; + DEBUG_PRINT("Seed found %u", seed); + } } if (seed == 0) break; diff --git a/src/random/glibc_random.c b/src/random/glibc_random.c new file mode 100644 index 0000000..46c99d0 --- /dev/null +++ b/src/random/glibc_random.c @@ -0,0 +1,58 @@ +/* + * Based on the code of Peter Selinger + * Reference: http://www.mathstat.dal.ca/~selinger/random/ + * + * The original code was modified to achieve better speed + */ + +#define GLIBC_PRNG_SIZE 344 +#define GLIBC_FAST_MAX_GEN 3 + +#if GLIBC_MAX_GEN < GLIBC_FAST_MAX_GEN + #error "GLIBC_MAX_GEN must be >= GLIBC_FAST_MAX_GEN" +#endif + +/* + * The +1 is used to keep the index inside the array after the increment, + * it doesn't really have a purpose besides that + */ +struct glibc_prng { + int index; + int state[GLIBC_PRNG_SIZE + GLIBC_MAX_GEN - GLIBC_FAST_MAX_GEN + 1]; +}; + +/* + * If only 3 numbers are generated then there's no need to store new values + */ +static unsigned int glibc_rand_fast(struct glibc_prng *prng) +{ + const int *state = prng->state; + const int i = prng->index++; + return ((unsigned int)(state[i - 31] + state[i - 3])) >> 1; +} + +/* + * There are no checks of bounds (GLIBC_MAX_GEN is the maximum number of times it can be called) + */ +static unsigned int glibc_rand(struct glibc_prng *prng) +{ + int *state = prng->state; + const int i = prng->index++; + state[i] = state[i - 31] + state[i - 3]; + return (unsigned int)state[i] >> 1; +} + +static void glibc_seed(struct glibc_prng *prng, int seed) +{ + int i = 0; + int *state = prng->state; + prng->index = GLIBC_PRNG_SIZE; + state[i++] = seed; + for ( ; i < 31; i++) { + state[i] = (16807LL * state[i - 1]) % 2147483647; + if (state[i] < 0) + state[i] += 2147483647; + } + for (i = 31; i < 34; i++) state[i] = state[i - 31]; + for (i = 34; i < 344; i++) state[i] = state[i - 31] + state[i - 3]; +} diff --git a/src/random/glibc_random_lazy.c b/src/random/glibc_random_lazy.c new file mode 100644 index 0000000..5f50a20 --- /dev/null +++ b/src/random/glibc_random_lazy.c @@ -0,0 +1,51 @@ +/* + * Based on the code of Peter Selinger + * Reference: http://www.mathstat.dal.ca/~selinger/random/ + * + * The original code was modified to achieve better speed + */ + +#include + +struct glibc_lazyprng { + int state[344]; +}; + +/* + * Return 1st generated element only + */ +static unsigned int glibc_rand1(struct glibc_lazyprng *prng) +{ + const int *state = prng->state; + return ((unsigned int)(state[344 - 31] + state[344 - 3])) >> 1; +} + +/* + * Fill a 4 elements array (to use with memcmp) + */ +static int *glibc_randfill(struct glibc_lazyprng *prng, uint32_t *arr) +{ + int *state = prng->state; + arr[0] = ((unsigned int)(state[344 - 31] + state[344 - 3])) >> 1; + arr[1] = ((unsigned int)(state[344 - 31 + 1] + state[344 - 3 + 1])) >> 1; + arr[2] = ((unsigned int)(state[344 - 31 + 2] + state[344 - 3 + 2])) >> 1; + arr[3] = ((unsigned int)(state[344 - 31 + 3] + arr[0])) >> 1; + return arr; +} + +/* + * Lazy seeding (stay 2 shorter) + */ +static void glibc_lazyseed(struct glibc_lazyprng *prng, int seed) +{ + int *state = prng->state; + int i = 0; + state[i++] = seed; + for ( ; i < 31; i++) { + state[i] = (16807LL * state[i - 1]) % 2147483647; + if (state[i] < 0) + state[i] += 2147483647; + } + for (i = 31; i < 34; i++) state[i] = state[i - 31]; + for (i = 34; i < 344 - 3 + 1; i++) state[i] = state[i - 31] + state[i - 3]; +} diff --git a/src/glibc_random_old.c b/src/random/glibc_random_old.c similarity index 95% rename from src/glibc_random_old.c rename to src/random/glibc_random_old.c index 2c6bbc2..bc9d63b 100644 --- a/src/glibc_random_old.c +++ b/src/random/glibc_random_old.c @@ -52,7 +52,7 @@ struct m_random_data { Note: The code takes advantage of the fact that both the front and rear pointers can't wrap on the same call by not testing the rear pointer if the front one has wrapped. Returns a 31-bit random number. */ -void m_random_r(struct m_random_data *buf, int32_t *result) +static void m_random_r(struct m_random_data *buf, int32_t *result) { int32_t *state = buf->state; int32_t *fptr = buf->fptr; @@ -82,7 +82,7 @@ void m_random_r(struct m_random_data *buf, int32_t *result) information a given number of times to get rid of any initial dependencies introduced by the L.C.R.N.G. Note that the initialization of randtbl[] for default usage relies on values produced by this routine. */ -void m_srandom_r(unsigned int seed, struct m_random_data *buf) +static void m_srandom_r(unsigned int seed, struct m_random_data *buf) { long int word; int i, kc; @@ -128,7 +128,7 @@ void m_srandom_r(unsigned int seed, struct m_random_data *buf) Note: The first thing we do is save the current state, if any, just like setstate so that it doesn't matter when initstate is called. Returns a pointer to the old state. */ -void m_initstate_r(unsigned int seed, char *arg_state, struct m_random_data *buf) +static void m_initstate_r(unsigned int seed, char *arg_state, struct m_random_data *buf) { int32_t *state = &((int32_t *)arg_state)[1]; /* First location */