#define PACKAGE_VERSION         TEXT("0.10.7/6")
#define AUTH_TIMEOUT_FIXL       2
#define AUTH_TIMEOUT_AUTO       6

#define MEM_CHUNK               10000
#define TRY_KEYS                150

// Number of trailers == number of sectors
// Mifare Classic 1k 16x64b = 16
#define NR_TRAILERS_1k          (16)
// Mifare Plus 2k 32x64b = 32
#define NR_TRAILERS_2k          (32)
// Mifare Classic Mini
#define NR_TRAILERS_MINI        (5)
// Mifare Classic 4k 32x64b + 8*256b = 40
#define NR_TRAILERS_4k          (40)

// Number of blocks
// Mifare Classic 1k
#define NR_BLOCKS_1k            0x3F
// Mifare Plus 2k
#define NR_BLOCKS_2k            0x7F
// Mifare Classic Mini
#define NR_BLOCKS_MINI          0x13
// Mifare Classic 4k
#define NR_BLOCKS_4k            0xFF

#define MAX_FRAME_LEN           33

// Used for counting nonce distances, explore [nd-value, nd+value]
#define DEFAULT_TOLERANCE       60
// Default number of distance probes
#define DEFAULT_DIST_NR         25

// Default number of probes for a key recovery for one sector
#define DEFAULT_PROBES_NR       50

// Number of sets with 32b keys
#define DEFAULT_SETS_NR         5

#define odd_parity(i) (( (i) ^ (i)>>1 ^ (i)>>2 ^ (i)>>3 ^ (i)>>4 ^ (i)>>5 ^ (i)>>6 ^ (i)>>7 ^ 1) & 0x01)

typedef struct {
    BYTE    KeyA[6];
    BYTE    KeyB[6];
    bool    foundKeyA;
    bool    foundKeyB;
    BYTE    trailer;            // Value of a trailer block
} sector;

typedef struct {
    DWORD   *distances;
    DWORD   median;
    DWORD   num_distances;
    DWORD   tolerance;
    BYTE    parity[3];          // used for 3 bits of parity information
} denonce;                      // Revealed information about nonce

typedef struct {
    sector  *sectors;           // Allocate later, we do not know the number of sectors yet
    sector  e_sector;           // Exploit sector
    BYTE    num_sectors;
    BYTE    num_blocks;
    DWORD   authuid;
} mftag;

typedef struct {
    DWORD64 *possibleKeys;
    DWORD   size;
} pKeys;

typedef struct {
  DWORD64   *brokenKeys;
  DWORD     size;
} bKeys;

typedef struct {
  DWORD64   key;
  int       count;
} countKeys;


void usage(FILE *stream);
int trailer_block(DWORD block);
int find_exploit_sector(mftag t);
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, PCCR pccr, denonce *d, pKeys *pk, char mode, bool dumpKeysA);
DWORD median(denonce d);
int __cdecl compar_int(const void *a, const void *b);
int valid_nonce(DWORD Nt, DWORD NtEnc, DWORD Ks1, BYTE *parity);
int __cdecl compar_special_int(const void *a, const void *b);
countKeys *uniqsort(DWORD64 *possibleKeys, DWORD size);
void num_to_bytes(DWORD64 n, DWORD len, BYTE *dest);
DWORD64 bytes_to_num(BYTE *src, DWORD len);
