mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
Merge branch 'master' into allin
update 201101
This commit is contained in:
commit
836ca5da40
9 changed files with 234 additions and 94 deletions
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -3,7 +3,31 @@ 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...
|
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]
|
## [unreleased][unreleased]
|
||||||
|
- Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...)
|
||||||
|
- ...
|
||||||
|
- Add Gallagher key checking/KDF on MIFARE Desfire (@NZSmartie)
|
||||||
|
- Add dictionaries with common words of proper size (@will-caruana)
|
||||||
|
- Add `hf mf supercard` (@iceman1001)
|
||||||
|
- Add initial suport for MIFARE Key Diversification, cf AN10922 (@NZSmartie)
|
||||||
|
- Change MIFARE detection improved (@VortixDev)
|
||||||
|
- Change `hf 14b sriread` to `hf 14b rdbl` and `hf 14b dump` (@iceman1001)
|
||||||
|
- Add continuous mode to `hf 14a reader` (@doegox and @iceman1001)
|
||||||
|
- Add `lf em 4x05_sniff` to allow extracting commands and passwords used be cloners. (@mwalker33)
|
||||||
- Removed 'hf iclass replay' - use the 'hf iclass dump' or 'hf iclass rdbl' with option "n" instead (@iceman1001). Concept taken from official repo (@pwpiwi)
|
- Removed 'hf iclass replay' - use the 'hf iclass dump' or 'hf iclass rdbl' with option "n" instead (@iceman1001). Concept taken from official repo (@pwpiwi)
|
||||||
|
- Add Destron FDX-A support (@doegox and @iceman1001)
|
||||||
|
- Add `lf em 4x05_chk` (@iceman1001)
|
||||||
|
- Add `lf em 4x05_unlock` tear-off (@doegox and @iceman1001)
|
||||||
|
- Added customizable 3DES key to hf mfu cauth (@socram8888)
|
||||||
|
- Add generic `hw tearoff` and hooks in various write commands (@doegox and @iceman1001)
|
||||||
|
- Add protect support for EM4x05 and fix various EM4x69/EM4x05 aspects (@doegox and @iceman1001)
|
||||||
|
- Add incognito option to client to avoid mangling history & logs (@doegox)
|
||||||
|
- Add option to hide/show plot sliders (@mwalker33)
|
||||||
|
- Add "</>" key bindings to realign demod plot on samples (@doegox)
|
||||||
|
- Add "T" key binding to trim plot (@doegox)
|
||||||
|
- Add units options to `data timescale` (@doegox)
|
||||||
|
- Add mouse scrolling to pan & zoom to plot (@doegox)
|
||||||
|
- Add hf_14b_mobib Lua script (@iceman1001)
|
||||||
|
- Add ASK CTx detection to hf 14b reader (@iceman1001 and @doegox)
|
||||||
- Add low level support for 14b' aka Innovatron (@doegox)
|
- Add low level support for 14b' aka Innovatron (@doegox)
|
||||||
- Add doc/cliparser.md (@mwalker33)
|
- Add doc/cliparser.md (@mwalker33)
|
||||||
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
|
- Add `hf 14b apdu` - send APDU over ISO14443B (@iceman1001)
|
||||||
|
|
|
@ -109,7 +109,8 @@ static uint32_t LastProxToAirDuration;
|
||||||
// Sequence E: 00001111 modulation with subcarrier during second half
|
// Sequence E: 00001111 modulation with subcarrier during second half
|
||||||
// Sequence F: 00000000 no modulation with subcarrier
|
// Sequence F: 00000000 no modulation with subcarrier
|
||||||
// Sequence COLL: 11111111 load modulation over the full bitlength.
|
// Sequence COLL: 11111111 load modulation over the full bitlength.
|
||||||
// Tricks the reader to think that multiple cards answer (at least one card with 1 and at least one card with 0).
|
// Tricks the reader to think that multiple cards answer.
|
||||||
|
// (at least one card with 1 and at least one card with 0)
|
||||||
// READER TO CARD - miller
|
// READER TO CARD - miller
|
||||||
// Sequence X: 00001100 drop after half a period
|
// Sequence X: 00001100 drop after half a period
|
||||||
// Sequence Y: 00000000 no drop
|
// Sequence Y: 00000000 no drop
|
||||||
|
@ -380,6 +381,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {
|
||||||
return true; // we are finished with decoding the raw data sequence
|
return true; // we are finished with decoding the raw data sequence
|
||||||
} else {
|
} else {
|
||||||
Uart14aReset(); // Nothing received - start over
|
Uart14aReset(); // Nothing received - start over
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
if (Uart.state == STATE_14A_START_OF_COMMUNICATION) { // error - must not follow directly after SOC
|
||||||
|
@ -2047,11 +2049,6 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
|
||||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
|
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY));
|
||||||
b = AT91C_BASE_SSC->SSC_RHR;
|
b = AT91C_BASE_SSC->SSC_RHR;
|
||||||
(void) b;
|
(void) b;
|
||||||
/*
|
|
||||||
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY));
|
|
||||||
b = AT91C_BASE_SSC->SSC_THR;
|
|
||||||
(void) b;
|
|
||||||
*/
|
|
||||||
|
|
||||||
// wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
|
// wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
|
||||||
for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
|
for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
|
||||||
|
@ -2070,13 +2067,6 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
|
||||||
AT91C_BASE_SSC->SSC_THR = resp[i++];
|
AT91C_BASE_SSC->SSC_THR = resp[i++];
|
||||||
FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
|
|
||||||
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
|
|
||||||
(void)b;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
|
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
|
||||||
|
@ -2341,6 +2331,8 @@ void iso14443a_antifuzz(uint32_t flags) {
|
||||||
uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||||
uint8_t *resp = BigBuf_malloc(20);
|
uint8_t *resp = BigBuf_malloc(20);
|
||||||
|
|
||||||
|
memset(received, 0x00, MAX_FRAME_SIZE);
|
||||||
|
memset(received, 0x00, MAX_PARITY_SIZE);
|
||||||
memset(resp, 0xFF, 20);
|
memset(resp, 0xFF, 20);
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
@ -2379,6 +2371,7 @@ void iso14443a_antifuzz(uint32_t flags) {
|
||||||
colpos = 8;
|
colpos = 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trigger a faulty/collision response
|
||||||
EmSendCmdEx(resp, 5, true);
|
EmSendCmdEx(resp, 5, true);
|
||||||
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("ANTICOLL or SELECT %x", received[1]);
|
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("ANTICOLL or SELECT %x", received[1]);
|
||||||
LED_D_INV();
|
LED_D_INV();
|
||||||
|
@ -2499,16 +2492,19 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
||||||
|
|
||||||
if (anticollision) {
|
if (anticollision) {
|
||||||
|
|
||||||
// SELECT_ALL
|
// SELECT_ALL
|
||||||
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
|
||||||
if (!ReaderReceive(resp, resp_par)) {
|
if (!ReaderReceive(resp, resp_par)) {
|
||||||
Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1);
|
Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||||
memset(uid_resp, 0, 5);
|
memset(uid_resp, 0, 5);
|
||||||
uint16_t uid_resp_bits = 0;
|
uint16_t uid_resp_bits = 0;
|
||||||
uint16_t collision_answer_offset = 0;
|
uint16_t collision_answer_offset = 0;
|
||||||
|
|
||||||
// anti-collision-loop:
|
// anti-collision-loop:
|
||||||
while (Demod.collisionPos) {
|
while (Demod.collisionPos) {
|
||||||
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
|
Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos);
|
||||||
|
@ -2527,6 +2523,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
||||||
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
|
ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL);
|
||||||
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
|
if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// finally, add the last bits and BCC of the UID
|
// finally, add the last bits and BCC of the UID
|
||||||
for (uint16_t i = collision_answer_offset; i < (Demod.len - 1) * 8; i++, uid_resp_bits++) {
|
for (uint16_t i = collision_answer_offset; i < (Demod.len - 1) * 8; i++, uid_resp_bits++) {
|
||||||
uint16_t UIDbit = (resp[i / 8] >> (i % 8)) & 0x01;
|
uint16_t UIDbit = (resp[i / 8] >> (i % 8)) & 0x01;
|
||||||
|
|
|
@ -583,7 +583,7 @@ all: $(BINS)
|
||||||
all-static: LDLIBS:=-static $(LDLIBS)
|
all-static: LDLIBS:=-static $(LDLIBS)
|
||||||
all-static: $(BINS)
|
all-static: $(BINS)
|
||||||
|
|
||||||
proxmark3: $(OBJS) amiibo cliparser jansson hardnested lua mbedtls reveng tinycbor whereami lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
|
proxmark3: $(OBJS) $(AMIIBOLIB) $(CLIPARSERLIB) $(JANSSONLIB) $(HARDNESTEDLIB) $(LUALIB) $(MBEDTLSLIB) $(REVENGLIB) $(TINYCBORLIB) $(WHEREAMILIB) lualibs/pm3_cmd.lua lualibs/mfc_default_keys.lua
|
||||||
$(info [=] LD $@)
|
$(info [=] LD $@)
|
||||||
$(Q)$(LD) $(PM3LDFLAGS) $(OBJS) $(LDLIBS) -o $@
|
$(Q)$(LD) $(PM3LDFLAGS) $(OBJS) $(LDLIBS) -o $@
|
||||||
|
|
||||||
|
@ -649,43 +649,43 @@ tarbin: $(BINS)
|
||||||
# local libraries targets #
|
# local libraries targets #
|
||||||
###########################
|
###########################
|
||||||
|
|
||||||
amiibo:
|
$(AMIIBOLIB):
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(AMIIBOLIBPATH) all
|
||||||
|
|
||||||
cliparser:
|
$(CLIPARSERLIB):
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERLIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(CLIPARSERLIBPATH) all
|
||||||
|
|
||||||
hardnested:
|
$(HARDNESTEDLIB):
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDLIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(HARDNESTEDLIBPATH) all
|
||||||
|
|
||||||
jansson:
|
$(JANSSONLIB):
|
||||||
ifneq ($(JANSSON_FOUND),1)
|
ifneq ($(JANSSON_FOUND),1)
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all
|
||||||
endif
|
endif
|
||||||
|
|
||||||
lua:
|
$(LUALIB):
|
||||||
ifneq ($(LUA_FOUND),1)
|
ifneq ($(LUA_FOUND),1)
|
||||||
$(info [*] MAKE $@ for $(LUAPLATFORM))
|
$(info [*] MAKE $@ for $(LUAPLATFORM))
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM)
|
$(Q)$(MAKE) --no-print-directory -C $(LUALIBPATH) $(LUAPLATFORM)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
mbedtls:
|
$(MBEDTLSLIB):
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all
|
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) OBJDIR=$(ROOT_DIR)$(OBJDIR) BINDIR=$(ROOT_DIR)$(OBJDIR) all
|
||||||
|
|
||||||
reveng:
|
$(REVENGLIB):
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) all
|
||||||
|
|
||||||
tinycbor:
|
$(TINYCBORLIB):
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) all
|
||||||
|
|
||||||
whereami:
|
$(WHEREAMILIB):
|
||||||
ifneq ($(WHEREAMI_FOUND),1)
|
ifneq ($(WHEREAMI_FOUND),1)
|
||||||
$(info [*] MAKE $@)
|
$(info [*] MAKE $@)
|
||||||
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all
|
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all
|
||||||
|
@ -695,7 +695,7 @@ endif
|
||||||
# misc #
|
# misc #
|
||||||
########
|
########
|
||||||
|
|
||||||
.PHONY: all clean install uninstall tarbin amiibo cliparser hardnested jansson lua mbedtls reveng tinycbor whereami
|
.PHONY: all clean install uninstall tarbin
|
||||||
|
|
||||||
# version.c should be remade on every compilation
|
# version.c should be remade on every compilation
|
||||||
src/version.c: default_version.c
|
src/version.c: default_version.c
|
||||||
|
|
|
@ -336,5 +336,21 @@ FFFFFF General Issuer Information (FIDs 00: MAD Version; 01: Card Holder; 02: Ca
|
||||||
"Name": "MemberCard",
|
"Name": "MemberCard",
|
||||||
"Description": "CAR2GO - Member Card",
|
"Description": "CAR2GO - Member Card",
|
||||||
"Type": "carsharing"
|
"Type": "carsharing"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AID": "2F81F4",
|
||||||
|
"Vendor": "Gallagher",
|
||||||
|
"Country": "NZ",
|
||||||
|
"Name": "Access control",
|
||||||
|
"Description": "Card Application Directory (CAD)",
|
||||||
|
"Type": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"AID": "2081F4",
|
||||||
|
"Vendor": "Gallagher",
|
||||||
|
"Country": "NZ",
|
||||||
|
"Name": "Access control",
|
||||||
|
"Description": "Cardax Card Data Application",
|
||||||
|
"Type": ""
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "mifare/mifaredefault.h" // default keys
|
#include "mifare/mifaredefault.h" // default keys
|
||||||
#include "mifare/ndef.h" // NDEF
|
#include "mifare/ndef.h" // NDEF
|
||||||
#include "mifare/mad.h"
|
#include "mifare/mad.h"
|
||||||
|
#include "generator.h"
|
||||||
|
|
||||||
#define MAX_KEY_LEN 24
|
#define MAX_KEY_LEN 24
|
||||||
#define MAX_KEYS_LIST_LEN 1024
|
#define MAX_KEYS_LIST_LEN 1024
|
||||||
|
@ -83,6 +84,16 @@ typedef struct mfdes_data {
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
} PACKED mfdes_data_t;
|
} PACKED mfdes_data_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t isOK;
|
||||||
|
uint8_t uid[7];
|
||||||
|
uint8_t uidlen;
|
||||||
|
uint8_t versionHW[7];
|
||||||
|
uint8_t versionSW[7];
|
||||||
|
uint8_t details[14];
|
||||||
|
} PACKED mfdes_info_res_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct mfdes_value {
|
typedef struct mfdes_value {
|
||||||
uint8_t fileno; //01
|
uint8_t fileno; //01
|
||||||
uint8_t value[16];
|
uint8_t value[16];
|
||||||
|
@ -664,6 +675,38 @@ static nxp_cardtype_t getCardType(uint8_t major, uint8_t minor) {
|
||||||
return DESFIRE_UNKNOWN;
|
return DESFIRE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int mfdes_get_info(mfdes_info_res_t *info) {
|
||||||
|
SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0);
|
||||||
|
PacketResponseNG resp;
|
||||||
|
|
||||||
|
if (WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
|
DropField();
|
||||||
|
return PM3_ETIMEOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(info, resp.data.asBytes, sizeof(mfdes_info_res_t));
|
||||||
|
|
||||||
|
if (resp.status != PM3_SUCCESS) {
|
||||||
|
switch (info->isOK) {
|
||||||
|
case 1:
|
||||||
|
PrintAndLogEx(WARNING, "Can't select card");
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
PrintAndLogEx(WARNING, "Card is most likely not DESFire. Wrong size UID");
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
default:
|
||||||
|
PrintAndLogEx(WARNING, _RED_("Command unsuccessful"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload) {
|
static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload) {
|
||||||
// 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
|
// 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
|
||||||
// 4 different crypto arg1 DES, 3DES, 3K3DES, AES
|
// 4 different crypto arg1 DES, 3DES, 3K3DES, AES
|
||||||
|
@ -715,6 +758,20 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp
|
||||||
if (g_debugMode) {
|
if (g_debugMode) {
|
||||||
PrintAndLogEx(INFO, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key)));
|
PrintAndLogEx(INFO, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key)));
|
||||||
}
|
}
|
||||||
|
} else if (payload->kdfAlgo == MFDES_KDF_ALGO_GALLAGHER) {
|
||||||
|
// We will overrite any provided KDF input since a gallagher specific KDF was requested.
|
||||||
|
payload->kdfInputLen = 11;
|
||||||
|
|
||||||
|
if (mfdes_kdf_input_gallagher(tag->info.uid, tag->info.uidlen, payload->keyno, tag->selected_application, payload->kdfInput, &payload->kdfInputLen) != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(FAILED, "Could not generate Gallagher KDF input");
|
||||||
|
}
|
||||||
|
|
||||||
|
mifare_kdf_an10922(key, payload->kdfInput, payload->kdfInputLen);
|
||||||
|
|
||||||
|
if (g_debugMode) {
|
||||||
|
PrintAndLogEx(INFO, " KDF Input: " _YELLOW_("%s"), sprint_hex(payload->kdfInput, payload->kdfInputLen));
|
||||||
|
PrintAndLogEx(INFO, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t subcommand = MFDES_AUTHENTICATE;
|
uint8_t subcommand = MFDES_AUTHENTICATE;
|
||||||
|
@ -2058,6 +2115,13 @@ static int desfire_authenticate(int cmdAuthMode, int cmdAuthAlgo, uint8_t *aid,
|
||||||
PrintAndLogEx(FAILED, "KDF AN10922 algo requires an input of length 1-31 bytes.");
|
PrintAndLogEx(FAILED, "KDF AN10922 algo requires an input of length 1-31 bytes.");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
case MFDES_KDF_ALGO_GALLAGHER:
|
||||||
|
// TODO: 2TDEA and 3TDEA keys use an input length of 1-15 bytes
|
||||||
|
if (cmdAuthAlgo != MFDES_ALGO_AES) {
|
||||||
|
PrintAndLogEx(FAILED, "Crypto algo not valid for the KDF AN10922 algo.");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
// KDF input arg is ignored as it'll be generated.
|
||||||
case MFDES_KDF_ALGO_NONE:
|
case MFDES_KDF_ALGO_NONE:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -3265,43 +3329,14 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) {
|
||||||
static int CmdHF14ADesInfo(const char *Cmd) {
|
static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
(void)Cmd; // Cmd is not used so far
|
(void)Cmd; // Cmd is not used so far
|
||||||
DropField();
|
DropField();
|
||||||
SendCommandNG(CMD_HF_DESFIRE_INFO, NULL, 0);
|
|
||||||
PacketResponseNG resp;
|
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500) == false) {
|
mfdes_info_res_t info;
|
||||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
int res = mfdes_get_info(&info);
|
||||||
DropField();
|
if (res != PM3_SUCCESS) {
|
||||||
return PM3_ETIMEOUT;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct p {
|
nxp_cardtype_t cardtype = getCardType(info.versionHW[3], info.versionHW[4]);
|
||||||
uint8_t isOK;
|
|
||||||
uint8_t uid[7];
|
|
||||||
uint8_t uidlen;
|
|
||||||
uint8_t versionHW[7];
|
|
||||||
uint8_t versionSW[7];
|
|
||||||
uint8_t details[14];
|
|
||||||
} PACKED;
|
|
||||||
|
|
||||||
struct p *package = (struct p *) resp.data.asBytes;
|
|
||||||
|
|
||||||
if (resp.status != PM3_SUCCESS) {
|
|
||||||
switch (package->isOK) {
|
|
||||||
case 1:
|
|
||||||
PrintAndLogEx(WARNING, "Can't select card");
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
PrintAndLogEx(WARNING, "Card is most likely not DESFire. Wrong size UID");
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
default:
|
|
||||||
PrintAndLogEx(WARNING, _RED_("Command unsuccessful"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return PM3_ESOFT;
|
|
||||||
}
|
|
||||||
|
|
||||||
nxp_cardtype_t cardtype = getCardType(package->versionHW[3], package->versionHW[4]);
|
|
||||||
if (cardtype == PLUS_EV1) {
|
if (cardtype == PLUS_EV1) {
|
||||||
PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`"));
|
PrintAndLogEx(INFO, "Card seems to be MIFARE Plus EV1. Try " _YELLOW_("`hf mfp info`"));
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
|
@ -3310,30 +3345,30 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
|
||||||
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
PrintAndLogEx(INFO, "-------------------------------------------------------------");
|
||||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(package->uid, package->uidlen));
|
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(info.uid, info.uidlen));
|
||||||
PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(package->details + 7, 5));
|
PrintAndLogEx(SUCCESS, " Batch number: " _GREEN_("%s"), sprint_hex(info.details + 7, 5));
|
||||||
PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), package->details[12], package->details[13]);
|
PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), info.details[12], info.details[13]);
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information"));
|
PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information"));
|
||||||
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(package->versionHW[0]));
|
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionHW[0]));
|
||||||
PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), package->versionHW[1]);
|
PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), info.versionHW[1]);
|
||||||
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), package->versionHW[2]);
|
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionHW[2]);
|
||||||
PrintAndLogEx(INFO, " Version: %s", getVersionStr(package->versionHW[3], package->versionHW[4]));
|
PrintAndLogEx(INFO, " Version: %s", getVersionStr(info.versionHW[3], info.versionHW[4]));
|
||||||
PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(package->versionHW[5]));
|
PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(info.versionHW[5]));
|
||||||
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(package->versionHW[6], true));
|
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionHW[6], true));
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Software Information"));
|
PrintAndLogEx(INFO, "--- " _CYAN_("Software Information"));
|
||||||
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(package->versionSW[0]));
|
PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionSW[0]));
|
||||||
PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), package->versionSW[1]);
|
PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), info.versionSW[1]);
|
||||||
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), package->versionSW[2]);
|
PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionSW[2]);
|
||||||
PrintAndLogEx(INFO, " Version: " _YELLOW_("%d.%d"), package->versionSW[3], package->versionSW[4]);
|
PrintAndLogEx(INFO, " Version: " _YELLOW_("%d.%d"), info.versionSW[3], info.versionSW[4]);
|
||||||
PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(package->versionSW[5]));
|
PrintAndLogEx(INFO, " Storage size: %s", getCardSizeStr(info.versionSW[5]));
|
||||||
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(package->versionSW[6], false));
|
PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionSW[6], false));
|
||||||
|
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Card capabilities"));
|
PrintAndLogEx(INFO, "--- " _CYAN_("Card capabilities"));
|
||||||
uint8_t major = package->versionSW[3];
|
uint8_t major = info.versionSW[3];
|
||||||
uint8_t minor = package->versionSW[4];
|
uint8_t minor = info.versionSW[4];
|
||||||
if (major == 0 && minor == 4)
|
if (major == 0 && minor == 4)
|
||||||
PrintAndLogEx(INFO, "\t0.4 - DESFire MF3ICD40, No support for APDU (only native commands)");
|
PrintAndLogEx(INFO, "\t0.4 - DESFire MF3ICD40, No support for APDU (only native commands)");
|
||||||
if (major == 0 && minor == 5)
|
if (major == 0 && minor == 5)
|
||||||
|
@ -3363,7 +3398,7 @@ static int CmdHF14ADesInfo(const char *Cmd) {
|
||||||
PrintAndLogEx(NORMAL, "");
|
PrintAndLogEx(NORMAL, "");
|
||||||
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
|
PrintAndLogEx(INFO, "--- " _CYAN_("Tag Signature"));
|
||||||
if (handler_desfire_signature(signature, &signature_len) == PM3_SUCCESS) {
|
if (handler_desfire_signature(signature, &signature_len) == PM3_SUCCESS) {
|
||||||
desfire_print_signature(package->uid, package->uidlen, signature, signature_len, cardtype);
|
desfire_print_signature(info.uid, info.uidlen, signature, signature_len, cardtype);
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(WARNING, "--- Card doesn't support GetSignature cmd");
|
PrintAndLogEx(WARNING, "--- Card doesn't support GetSignature cmd");
|
||||||
}
|
}
|
||||||
|
@ -3911,7 +3946,7 @@ static int CmdHF14ADesAuth(const char *Cmd) {
|
||||||
arg_strx0("a", "aid", "<aid>", "AID used for authentification (HEX 3 bytes)"),
|
arg_strx0("a", "aid", "<aid>", "AID used for authentification (HEX 3 bytes)"),
|
||||||
arg_int0("n", "keyno", "<keyno>", "Key number used for authentification"),
|
arg_int0("n", "keyno", "<keyno>", "Key number used for authentification"),
|
||||||
arg_str0("k", "key", "<Key>", "Key for checking (HEX 8-24 bytes)"),
|
arg_str0("k", "key", "<Key>", "Key for checking (HEX 8-24 bytes)"),
|
||||||
arg_int0("d", "kdf", "<kdf>", "Key Derivation Function (KDF) (0=None, 1=AN10922)"),
|
arg_int0("d", "kdf", "<kdf>", "Key Derivation Function (KDF) (0=None, 1=AN10922, 2=Gallagher)"),
|
||||||
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
|
@ -4039,6 +4074,7 @@ static int AuthCheckDesfire(uint8_t *aid,
|
||||||
uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t deskeyListLen,
|
uint8_t deskeyList[MAX_KEYS_LIST_LEN][8], uint32_t deskeyListLen,
|
||||||
uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t aeskeyListLen,
|
uint8_t aeskeyList[MAX_KEYS_LIST_LEN][16], uint32_t aeskeyListLen,
|
||||||
uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], uint32_t k3kkeyListLen,
|
uint8_t k3kkeyList[MAX_KEYS_LIST_LEN][24], uint32_t k3kkeyListLen,
|
||||||
|
uint8_t cmdKdfAlgo, uint8_t kdfInputLen, uint8_t *kdfInput,
|
||||||
uint8_t foundKeys[4][0xE][24 + 1], bool *result) {
|
uint8_t foundKeys[4][0xE][24 + 1], bool *result) {
|
||||||
|
|
||||||
uint32_t curaid = (aid[0] & 0xFF) + ((aid[1] & 0xFF) << 8) + ((aid[2] & 0xFF) << 16);
|
uint32_t curaid = (aid[0] & 0xFF) + ((aid[1] & 0xFF) << 8) + ((aid[2] & 0xFF) << 16);
|
||||||
|
@ -4055,6 +4091,14 @@ static int AuthCheckDesfire(uint8_t *aid,
|
||||||
bool aes = false;
|
bool aes = false;
|
||||||
bool k3kdes = false;
|
bool k3kdes = false;
|
||||||
|
|
||||||
|
uint8_t num_keys = 0;
|
||||||
|
uint8_t key_setting = 0;
|
||||||
|
res = handler_desfire_getkeysettings(&key_setting, &num_keys);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
PrintAndLogEx(ERR, "Could not get key settings");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
if (memcmp(aid, "\x00\x00\x00", 3) != 0) {
|
if (memcmp(aid, "\x00\x00\x00", 3) != 0) {
|
||||||
uint8_t file_ids[33] = {0};
|
uint8_t file_ids[33] = {0};
|
||||||
uint32_t file_ids_len = 0;
|
uint32_t file_ids_len = 0;
|
||||||
|
@ -4086,7 +4130,7 @@ static int AuthCheckDesfire(uint8_t *aid,
|
||||||
usedkeys[read_access] = 1;
|
usedkeys[read_access] = 1;
|
||||||
|
|
||||||
if (res == PM3_SUCCESS) {
|
if (res == PM3_SUCCESS) {
|
||||||
switch (fileset_len >> 6) {
|
switch (num_keys >> 6) {
|
||||||
case 0:
|
case 0:
|
||||||
des = true;
|
des = true;
|
||||||
tdes = true;
|
tdes = true;
|
||||||
|
@ -4192,7 +4236,7 @@ static int AuthCheckDesfire(uint8_t *aid,
|
||||||
if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) {
|
if (usedkeys[keyno] == 1 && foundKeys[2][keyno][0] == 0) {
|
||||||
for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
|
for (uint32_t curkey = 0; curkey < aeskeyListLen; curkey++) {
|
||||||
mfdes_auth_res_t rpayload;
|
mfdes_auth_res_t rpayload;
|
||||||
error = desfire_authenticate(MFDES_AUTH_AES, MFDES_ALGO_AES, aid, aeskeyList[curkey], keyno, 0, 0, NULL, &rpayload);
|
error = desfire_authenticate(MFDES_AUTH_AES, MFDES_ALGO_AES, aid, aeskeyList[curkey], keyno, cmdKdfAlgo, kdfInputLen, kdfInput, &rpayload);
|
||||||
if (error == PM3_SUCCESS) {
|
if (error == PM3_SUCCESS) {
|
||||||
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
|
PrintAndLogEx(SUCCESS, "AID 0x%06X, Found AES Key %u : " _GREEN_("%s"), curaid, keyno, sprint_hex(aeskeyList[curkey], 16));
|
||||||
foundKeys[2][keyno][0] = 0x01;
|
foundKeys[2][keyno][0] = 0x01;
|
||||||
|
@ -4281,6 +4325,8 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
arg_str0(NULL, "startp2b", "<Pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
|
arg_str0(NULL, "startp2b", "<Pattern>", "Start key (2-byte HEX) for 2-byte search (use with `--pattern2b`)"),
|
||||||
arg_str0("j", "json", "<file>", "Json file to save keys"),
|
arg_str0("j", "json", "<file>", "Json file to save keys"),
|
||||||
arg_lit0("v", "verbose", "Verbose mode."),
|
arg_lit0("v", "verbose", "Verbose mode."),
|
||||||
|
arg_int0("f", "kdf", "<kdf>", "Key Derivation Function (KDF) (0=None, 1=AN10922, 2=Gallagher)"),
|
||||||
|
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||||
|
@ -4360,6 +4406,12 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
|
|
||||||
bool verbose = arg_get_lit(ctx, 8);
|
bool verbose = arg_get_lit(ctx, 8);
|
||||||
|
|
||||||
|
// Get KDF input
|
||||||
|
uint8_t kdfInput[31] = {0};
|
||||||
|
int kdfInputLen = 0;
|
||||||
|
uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0);
|
||||||
|
CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
// 1-byte pattern search mode
|
// 1-byte pattern search mode
|
||||||
|
@ -4401,24 +4453,20 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
endFilePosition = 0;
|
endFilePosition = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aeskeyListLen == 0) {
|
if (aeskeyListLen == 0 && deskeyListLen == 0 && k3kkeyListLen == 0) {
|
||||||
PrintAndLogEx(ERR, "Aes key list is empty. Nothing to check.");
|
PrintAndLogEx(ERR, "No keys provided. Nothing to check.");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (aeskeyListLen != 0) {
|
||||||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " aes keys", aeskeyListLen);
|
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " aes keys", aeskeyListLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deskeyListLen == 0) {
|
if (deskeyListLen != 0) {
|
||||||
PrintAndLogEx(ERR, "Des key list is empty. Nothing to check.");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " des keys", deskeyListLen);
|
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " des keys", deskeyListLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k3kkeyListLen == 0) {
|
if (k3kkeyListLen != 0) {
|
||||||
PrintAndLogEx(ERR, "K3k key list is empty. Nothing to check.");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen);
|
PrintAndLogEx(INFO, "Loaded " _YELLOW_("%"PRIu32) " k3kdes keys", k3kkeyListLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4429,6 +4477,17 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
uint8_t app_ids[78] = {0};
|
uint8_t app_ids[78] = {0};
|
||||||
uint32_t app_ids_len = 0;
|
uint32_t app_ids_len = 0;
|
||||||
|
|
||||||
|
clearCommandBuffer();
|
||||||
|
|
||||||
|
mfdes_info_res_t info = {0};
|
||||||
|
res = mfdes_get_info(&info);
|
||||||
|
if (res != PM3_SUCCESS) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// TODO: Store this UID someowhere not global
|
||||||
|
memcpy(tag->info.uid, info.uid, info.uidlen);
|
||||||
|
tag->info.uidlen = info.uidlen;
|
||||||
|
|
||||||
if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) {
|
if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) {
|
||||||
PrintAndLogEx(ERR, "Can't get list of applications on tag");
|
PrintAndLogEx(ERR, "Can't get list of applications on tag");
|
||||||
DropField();
|
DropField();
|
||||||
|
@ -4437,7 +4496,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
|
|
||||||
if (aidlength != 0) {
|
if (aidlength != 0) {
|
||||||
memcpy(&app_ids[0], aid, 3);
|
memcpy(&app_ids[0], aid, 3);
|
||||||
app_ids_len = 1;
|
app_ids_len = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t x = 0; x < app_ids_len / 3; x++) {
|
for (uint32_t x = 0; x < app_ids_len / 3; x++) {
|
||||||
|
@ -4445,7 +4504,7 @@ static int CmdHF14aDesChk(const char *Cmd) {
|
||||||
uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
|
uint32_t curaid = (app_ids[x * 3] & 0xFF) + ((app_ids[(x * 3) + 1] & 0xFF) << 8) + ((app_ids[(x * 3) + 2] & 0xFF) << 16);
|
||||||
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
|
PrintAndLogEx(ERR, "Checking aid 0x%06X...", curaid);
|
||||||
|
|
||||||
res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, foundKeys, &result);
|
res = AuthCheckDesfire(&app_ids[x * 3], deskeyList, deskeyListLen, aeskeyList, aeskeyListLen, k3kkeyList, k3kkeyListLen, cmdKDFAlgo, kdfInputLen, kdfInput, foundKeys, &result);
|
||||||
if (res == PM3_EOPABORTED) {
|
if (res == PM3_EOPABORTED) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -377,7 +377,7 @@ static int CmdHFMFPInfo(const char *Cmd) {
|
||||||
// DESFire answers 0x1C or 67 00
|
// DESFire answers 0x1C or 67 00
|
||||||
// Plus answers 0x0B, 0x09, 0x06
|
// Plus answers 0x0B, 0x09, 0x06
|
||||||
// Which tag answers 6D 00 ??
|
// Which tag answers 6D 00 ??
|
||||||
if (data[0] != 0x0b && data[0] != 0x09 && data[0] != 0x1C && data[0] != 0x67) {
|
if (data[0] != 0x0b && data[0] != 0x09 && data[0] != 0x1C && data[0] != 0x67 && data[0] != 0x6d) {
|
||||||
PrintAndLogEx(INFO, _RED_("Send copy to iceman of this command output!"));
|
PrintAndLogEx(INFO, _RED_("Send copy to iceman of this command output!"));
|
||||||
PrintAndLogEx(INFO, "data: %s", sprint_hex(data, datalen));
|
PrintAndLogEx(INFO, "data: %s", sprint_hex(data, datalen));
|
||||||
}
|
}
|
||||||
|
|
|
@ -423,6 +423,47 @@ uint32_t lf_t55xx_white_pwdgen(uint32_t id) {
|
||||||
return pwd;
|
return pwd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gallagher Desfire Key Diversification Input for Cardax Card Data Application
|
||||||
|
int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen) {
|
||||||
|
if (uid == NULL || (uidLen != 4 && uidLen != 7) || keyNo > 2 || kdfInputOut == NULL || kdfInputLen == NULL) {
|
||||||
|
if (g_debugMode) {
|
||||||
|
PrintAndLogEx(WARNING, "Invalid arguments");
|
||||||
|
}
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify the AppID is a valid Gallagher AppID
|
||||||
|
if ((aid & 0xF0FFFF) != 0x2081F4) {
|
||||||
|
if (g_debugMode) {
|
||||||
|
PrintAndLogEx(WARNING, "Invalid Gallagher AID %06X", aid);
|
||||||
|
}
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
// If the keyNo == 1, then omit the UID.
|
||||||
|
if (keyNo != 1) {
|
||||||
|
if (*kdfInputLen < (4 + uidLen)) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(kdfInputOut, uid, uidLen);
|
||||||
|
len += uidLen;
|
||||||
|
} else if (*kdfInputLen < 4) {
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
kdfInputOut[len++] = keyNo;
|
||||||
|
|
||||||
|
kdfInputOut[len++] = aid & 0xff;
|
||||||
|
kdfInputOut[len++] = (aid >> 8) & 0xff;
|
||||||
|
kdfInputOut[len++] = (aid >> 16) & 0xff;
|
||||||
|
|
||||||
|
*kdfInputLen = len;
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
// Self tests
|
// Self tests
|
||||||
//------------------------------------
|
//------------------------------------
|
||||||
|
|
|
@ -43,5 +43,7 @@ int mfc_algo_sky_all(uint8_t *uid, uint8_t *keys);
|
||||||
|
|
||||||
uint32_t lf_t55xx_white_pwdgen(uint32_t id);
|
uint32_t lf_t55xx_white_pwdgen(uint32_t id);
|
||||||
|
|
||||||
|
int mfdes_kdf_input_gallagher(uint8_t *uid, uint8_t uidLen, uint8_t keyNo, uint32_t aid, uint8_t *kdfInputOut, uint8_t *kdfInputLen);
|
||||||
|
|
||||||
int generator_selftest(void);
|
int generator_selftest(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -97,6 +97,7 @@ typedef enum {
|
||||||
typedef enum {
|
typedef enum {
|
||||||
MFDES_KDF_ALGO_NONE = 0,
|
MFDES_KDF_ALGO_NONE = 0,
|
||||||
MFDES_KDF_ALGO_AN10922 = 1,
|
MFDES_KDF_ALGO_AN10922 = 1,
|
||||||
|
MFDES_KDF_ALGO_GALLAGHER = 2,
|
||||||
} mifare_des_kdf_algo_t;
|
} mifare_des_kdf_algo_t;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue