/*
Package:
MiFare Classic Universal toolKit (MFCUK)
Package version:
0.1
Filename:
mfcuk_mifare.h
Description:
MFCUK defines and function prototypes header file extending
mainly libnfc's "mifare.h" interface/functionality.
Contact, bug-reports:
http://andreicostin.com/
mailto:zveriu@gmail.com
License:
GPL2 (see below), Copyright (C) 2009, Andrei Costin
* @file mfcuk_mifare.h
* @brief
*/
/*
VERSION HISTORY
--------------------------------------------------------------------------------
| Number : 0.1
| dd/mm/yyyy : 23/11/2009
| Author : zveriu@gmail.com, http://andreicostin.com
| Description: Moved bulk of defines and functions from "mfcuk_keyrecovery_darkside.c"
--------------------------------------------------------------------------------
*/
/*
LICENSE
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 2 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 .
*/
#ifndef _MFCUK_MIFARE_H_
#define _MFCUK_MIFARE_H_
#include
#include
#include
#include "mifare.h"
#define MIFARE_CLASSIC_UID_BYTELENGTH 4 // Length of a Mifare Classic UID in bytes
#define MIFARE_CLASSIC_KEY_BYTELENGTH 6 // Length of a Mifare Classic key in bytes
#define MIFARE_CLASSIC_1K_NAME "MC1K"
#define MIFARE_CLASSIC_4K_NAME "MC4K"
#define MIFARE_CLASSIC_UNKN_NAME "UNKN"
#define MIFARE_CLASSIC_1K 0x08 // MF1ICS50 Functional Specifications - 0x08
#define MIFARE_CLASSIC_4K 0x18 // MF1ICS70 Functional Specifications - 0x18
#define MIFARE_DESFIRE 0x20 // XXXXXXXX Functional Specifications - 0x20
#define MIFARE_CLASSIC_1K_RATB 0x88 // Infineon Licensed Mifare 1K = 0x88 (thanks JPS)
#define MIFARE_CLASSIC_4K_SKGT 0x98 // Infineon Licensed Mifare 4K = 0x98???
#define IS_MIFARE_CLASSIC_1K(ats_sak) ( ((ats_sak) == MIFARE_CLASSIC_1K) || ((ats_sak) == MIFARE_CLASSIC_1K_RATB) )
#define IS_MIFARE_CLASSIC_4K(ats_sak) ( ((ats_sak) == MIFARE_CLASSIC_4K) || ((ats_sak) == MIFARE_CLASSIC_4K_SKGT) )
#define IS_MIFARE_DESFIRE(ats_sak) ( ((ats_sak) == MIFARE_DESFIRE) )
#define IS_MIFARE_CLASSIC_1K_TAG(tag) IS_MIFARE_CLASSIC_1K(tag->amb[0].mbm.btUnknown)
#define IS_MIFARE_CLASSIC_4K_TAG(tag) IS_MIFARE_CLASSIC_4K(tag->amb[0].mbm.btUnknown)
#define IS_MIFARE_DESFIRE_TAG(tag) IS_MIFARE_DESFIRE(tag->amb[0].mbm.btUnknown)
#define MIFARE_CLASSIC_BYTES_PER_BLOCK 16 // Common for Mifare Classic 1K and Mifare Classic 4K
#define MIFARE_CLASSIC_INVALID_BLOCK 0xFFFFFFFF
#define MIFARE_CLASSIC_1K_MAX_SECTORS 16
#define MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR 4
#define MIFARE_CLASSIC_1K_MAX_BLOCKS ( (MIFARE_CLASSIC_1K_MAX_SECTORS) * (MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR) )
#define MIFARE_CLASSIC_4K_MAX_SECTORS1 32
#define MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1 MIFARE_CLASSIC_1K_BLOCKS_PER_SECTOR // Possibly NXP made it for Mifare 1K backward compatibility
#define MIFARE_CLASSIC_4K_MAX_BLOCKS1 ( (MIFARE_CLASSIC_4K_MAX_SECTORS1) * (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR1) )
#define MIFARE_CLASSIC_4K_MAX_SECTORS2 8
#define MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2 16
#define MIFARE_CLASSIC_4K_MAX_BLOCKS2 ( (MIFARE_CLASSIC_4K_MAX_SECTORS2) * (MIFARE_CLASSIC_4K_BLOCKS_PER_SECTOR2) )
#define MIFARE_CLASSIC_4K_MAX_SECTORS ( (MIFARE_CLASSIC_4K_MAX_SECTORS1) + (MIFARE_CLASSIC_4K_MAX_SECTORS2) )
#define MIFARE_CLASSIC_4K_MAX_BLOCKS ( (MIFARE_CLASSIC_4K_MAX_BLOCKS1) + (MIFARE_CLASSIC_4K_MAX_BLOCKS2) )
#define MFCUK_EXTENDED_DESCRIPTION_LENGTH 128
// Define an extended type of dump, basically a wrapper dump around basic tag dump
typedef struct {
uint32_t uid; // looks redundant, but it is easier to use dmp.uid instead of dmp.amb.mbm.abtUID[0]...[3]
uint8_t type; // ATS/SAK from ti.tia.btSak, example 0x08h for Mifare 1K, 0x18h for Mifare 4K
char datetime[14]; // non-zero-terminated date-time of dump in format YYYYMMDDH24MISS, example 20091114231541 - 14 Nov 2009, 11:15:41 PM
char description[MFCUK_EXTENDED_DESCRIPTION_LENGTH]; // a description of the tag dump, example "RATB_DUMP_BEFORE_PAY"
mifare_classic_tag tag_basic;
} mifare_classic_tag_ext;
// Define type of keys (A or B) in NXP notation
typedef enum {
keyA = 0x60,
keyB = 0x61,
} mifare_key_type;
// Default keys used as a *BIG* mistake in many applications - especially System Integrators should pay attention!
extern uint8_t mfcuk_default_keys[][MIFARE_CLASSIC_KEY_BYTELENGTH];
extern int mfcuk_default_keys_num;
bool is_valid_block(uint8_t bTagType, uint32_t uiBlock);
bool is_valid_sector(uint8_t bTagType, uint32_t uiSector);
bool is_first_block(uint8_t bTagType, uint32_t uiBlock);
bool is_trailer_block(uint8_t bTagType, uint32_t uiBlock);
uint32_t get_first_block(uint8_t bTagType, uint32_t uiBlock);
uint32_t get_trailer_block(uint8_t bTagType, uint32_t uiBlock);
bool is_big_sector(uint8_t bTagType, uint32_t uiSector);
uint32_t get_first_block_for_sector(uint8_t bTagType, uint32_t uiSector);
uint32_t get_trailer_block_for_sector(uint8_t bTagType, uint32_t uiSector);
uint32_t get_sector_for_block(uint8_t bTagType, uint32_t uiBlock);
bool is_first_sector(uint8_t bTagType, uint32_t uiSector);
bool is_first_big_sector(uint8_t bTagType, uint32_t uiSector);
bool is_first_small_sector(uint8_t bTagType, uint32_t uiSector);
bool is_last_sector(uint8_t bTagType, uint32_t uiSector);
bool is_last_big_sector(uint8_t bTagType, uint32_t uiSector);
bool is_last_small_sector(uint8_t bTagType, uint32_t uiSector);
void test_mifare_classic_blocks_sectors_functions(uint8_t bTagType);
bool mfcuk_save_tag_dump(const char *filename, mifare_classic_tag *tag);
bool mfcuk_save_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext);
bool mfcuk_load_tag_dump(const char *filename, mifare_classic_tag *tag);
bool mfcuk_load_tag_dump_ext(const char *filename, mifare_classic_tag_ext *tag_ext);
void print_mifare_classic_tag_keys(const char *title, mifare_classic_tag *tag);
bool mfcuk_key_uint64_to_arr(const uint64_t *ui64Key, uint8_t *arr6Key);
bool mfcuk_key_arr_to_uint64(const uint8_t *arr6Key, uint64_t *ui64Key);
#endif // _MFCUK_MIFARE_H_