diff --git a/README.md b/README.md index 3ee2915..fcfb6a7 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,7 @@ cd pixiewps*/ cd src/ make ``` +Optionally, you can run make OPENSSL=1 to use faster OpenSSL SHA256 functions. **Install** diff --git a/src/Makefile b/src/Makefile index d3f728f..04f1754 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,12 +1,20 @@ -CFLAGS ?= -std=c99 -O3 +CFLAGS = -std=c99 -O3 + +LIBS = -lpthread +ifeq ($(OPENSSL),1) +LIBS += -lcrypto +CFLAGS += -DUSE_OPENSSL +else +CRYPTO = mbedtls/sha256.c mbedtls/md.c mbedtls/md_wrap.c +endif + +PREFIX = /usr +BINDIR = $(PREFIX)/bin TARGET = pixiewps -CRYPTO = mbedtls/sha256.c mbedtls/md.c mbedtls/md_wrap.c SOURCE = $(TARGET).c $(CRYPTO) -LIBS = -lpthread -PREFIX ?= /usr -BINDIR = $(PREFIX)/bin +-include config.mak all: $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TARGET) $(SOURCE) $(LIBS) $(LDFLAGS) diff --git a/src/config.h b/src/config.h index 41ba711..f73845f 100644 --- a/src/config.h +++ b/src/config.h @@ -25,9 +25,9 @@ #include "mbedtls/md_internal.h" #include "mbedtls/sha256.h" -#define sha256(i, l, d) mbedtls_sha256(i, l, d, 0) +#define sha256(i, l, d) sha256_full(i, l, d) #define hmac_sha256(k, l, i, n, o) \ - mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), k, l, i, n, o) + hmac_sha256_full(k, l, i, n, o) #define u8 uint8_t #define u16 uint16_t diff --git a/src/crypto/hmac_sha256.c b/src/crypto/hmac_sha256.c new file mode 100644 index 0000000..481d1b8 --- /dev/null +++ b/src/crypto/hmac_sha256.c @@ -0,0 +1,119 @@ +/* public domain hmac_sha256 implementation written by rofl0r for pixiewps */ + +#include +#include +#ifdef USE_OPENSSL +#include +#else +#include "../mbedtls/sha256.h" +#define SHA256_CTX mbedtls_sha256_context +#define SHA256_Init(x) do { mbedtls_sha256_init(x); mbedtls_sha256_starts(x, 0); } while(0) +#define SHA256_Update(x, y, z) mbedtls_sha256_update(x, y, z) +#define SHA256_Final(y, x) mbedtls_sha256_finish(x, y) +#endif + +#define PAD_SIZE 64 +#define HASH_SIZE 32 + +static void sha256_full(const uint8_t *input, size_t ilen, uint8_t *output) +{ + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, input, ilen); + SHA256_Final(output, &ctx); +} + +static void hmac_sha256_full(const uint8_t *key, size_t keylen, + const uint8_t *input, size_t ilen, uint8_t *output) +{ + size_t i; + uint8_t opad[PAD_SIZE], ipad[PAD_SIZE], hash[HASH_SIZE]; + SHA256_CTX ctx; + + memset(ipad, 0x36, PAD_SIZE); + memset(opad, 0x5C, PAD_SIZE); + + if (keylen > PAD_SIZE) { + + SHA256_Init(&ctx); + SHA256_Update(&ctx, key, keylen); + SHA256_Final(hash, &ctx); + + for (i = 0; i < HASH_SIZE; i++) { + ipad[i] ^= hash[i]; + opad[i] ^= hash[i]; + } + + } else for (i = 0; i < keylen; i++) { + ipad[i] ^= key[i]; + opad[i] ^= key[i]; + } + + SHA256_Init(&ctx); + SHA256_Update(&ctx, ipad, PAD_SIZE); + SHA256_Update(&ctx, input, ilen); + SHA256_Final(hash, &ctx); + + SHA256_Init(&ctx); + SHA256_Update(&ctx, opad, PAD_SIZE); + SHA256_Update(&ctx, hash, sizeof hash); + + SHA256_Final(output, &ctx); +} + +struct hmac_ctx { + SHA256_CTX ictx; + SHA256_CTX octx; +}; + +static void hmac_sha256_init(struct hmac_ctx *hctx, const uint8_t *key, size_t keylen) +{ + size_t i; + uint8_t opad[PAD_SIZE], ipad[PAD_SIZE], hash[HASH_SIZE]; + SHA256_CTX ctx; + + memset(ipad, 0x36, PAD_SIZE); + memset(opad, 0x5C, PAD_SIZE); + + if (keylen > PAD_SIZE) { + + SHA256_Init(&ctx); + SHA256_Update(&ctx, key, keylen); + SHA256_Final(hash, &ctx); + + for (i = 0; iictx); + SHA256_Update(&hctx->ictx, ipad, PAD_SIZE); + + SHA256_Init(&hctx->octx); + SHA256_Update(&hctx->octx, opad, PAD_SIZE); +} + + +static void hmac_sha256_yield(const struct hmac_ctx *hctx, + const uint8_t *input, size_t ilen, uint8_t *output) +{ + SHA256_CTX ctx; + uint8_t hash[HASH_SIZE]; + + memcpy(&ctx, &hctx->ictx, sizeof(ctx)); + + SHA256_Update(&ctx, input, ilen); + SHA256_Final(hash, &ctx); + + + memcpy(&ctx, &hctx->octx, sizeof(ctx)); + + SHA256_Update(&ctx, hash, sizeof hash); + SHA256_Final(output, &ctx); +} + diff --git a/src/pixiewps.c b/src/pixiewps.c index 25eed09..304fb46 100644 --- a/src/pixiewps.c +++ b/src/pixiewps.c @@ -38,6 +38,7 @@ #include "pixiewps.h" #include "crypto/crypto_internal-modexp.c" #include "crypto/aes-cbc.c" +#include "crypto/hmac_sha256.c" #include "utils.h" #include "wps.h" #include "version.h" @@ -1482,17 +1483,17 @@ static int int_pow(int a, int exp) } /* return non-zero if pin half is correct, zero otherwise */ -static int check_pin_half(const char pinhalf[4], uint8_t *psk, const uint8_t *es, struct global *wps, const uint8_t *ehash) +static int check_pin_half(const struct hmac_ctx *hctx, const char pinhalf[4], uint8_t *psk, const uint8_t *es, struct global *wps, const uint8_t *ehash) { uint8_t buffer[WPS_SECRET_NONCE_LEN + WPS_PSK_LEN + WPS_PKEY_LEN * 2]; uint8_t result[WPS_HASH_LEN]; - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, (unsigned char *)pinhalf, 4, psk); + hmac_sha256_yield(hctx, pinhalf, 4, psk); memcpy(buffer, es, WPS_SECRET_NONCE_LEN); memcpy(buffer + WPS_SECRET_NONCE_LEN, psk, WPS_PSK_LEN); memcpy(buffer + WPS_SECRET_NONCE_LEN + WPS_PSK_LEN, wps->pke, WPS_PKEY_LEN); memcpy(buffer + WPS_SECRET_NONCE_LEN + WPS_PSK_LEN + WPS_PKEY_LEN, wps->pkr, WPS_PKEY_LEN); - hmac_sha256(wps->authkey, WPS_AUTHKEY_LEN, buffer, sizeof buffer, result); + hmac_sha256_yield(hctx, buffer, sizeof buffer, result); return !memcmp(result, ehash, WPS_HASH_LEN); } @@ -1525,10 +1526,12 @@ static int crack_first_half(struct global *wps, char *pin, const uint8_t *es1_ov unsigned first_half; uint8_t psk[WPS_HASH_LEN]; + struct hmac_ctx hc; + hmac_sha256_init(&hc, wps->authkey, WPS_AUTHKEY_LEN); for (first_half = 0; first_half < 10000; first_half++) { uint_to_char_array(first_half, 4, pin); - if (check_pin_half(pin, psk, es1, wps, wps->e_hash1)) { + if (check_pin_half(&hc, pin, psk, es1, wps, wps->e_hash1)) { pin[4] = 0; /* make sure pin string is zero-terminated */ memcpy(wps->psk1, psk, sizeof psk); return 1; @@ -1549,12 +1552,15 @@ static int crack_second_half(struct global *wps, char *pin) unsigned second_half, first_half = atoi(pin); char *s_pin = pin + strlen(pin); uint8_t psk[WPS_HASH_LEN]; + struct hmac_ctx hc; + hmac_sha256_init(&hc, wps->authkey, WPS_AUTHKEY_LEN); + for (second_half = 0; second_half < 1000; second_half++) { unsigned int checksum_digit = wps_pin_checksum(first_half * 1000 + second_half); unsigned int c_second_half = second_half * 10 + checksum_digit; uint_to_char_array(c_second_half, 4, s_pin); - if (check_pin_half(s_pin, psk, wps->e_s2, wps, wps->e_hash2)) { + if (check_pin_half(&hc, s_pin, psk, wps->e_s2, wps, wps->e_hash2)) { memcpy(wps->psk2, psk, sizeof psk); pin[8] = 0; return 1; @@ -1569,7 +1575,7 @@ static int crack_second_half(struct global *wps, char *pin) } uint_to_char_array(second_half, 4, s_pin); - if (check_pin_half(s_pin, psk, wps->e_s2, wps, wps->e_hash2)) { + if (check_pin_half(&hc, s_pin, psk, wps->e_s2, wps, wps->e_hash2)) { memcpy(wps->psk2, psk, sizeof psk); pin[8] = 0; /* make sure pin string is zero-terminated */ return 1;