mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
gen4 commands refactoring
This commit is contained in:
parent
7692f09760
commit
e32ca56084
7 changed files with 208 additions and 170 deletions
|
@ -279,6 +279,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/mifare/mifare4.c
|
||||
${PM3_ROOT}/client/src/mifare/mifaredefault.c
|
||||
${PM3_ROOT}/client/src/mifare/mifarehost.c
|
||||
${PM3_ROOT}/client/src/mifare/gen4.c
|
||||
${PM3_ROOT}/client/src/nfc/ndef.c
|
||||
${PM3_ROOT}/client/src/mifare/lrpcrypto.c
|
||||
${PM3_ROOT}/client/src/mifare/desfirecrypto.c
|
||||
|
|
|
@ -703,6 +703,7 @@ SRCS = mifare/aiddesfire.c \
|
|||
mifare/mifare4.c \
|
||||
mifare/mifaredefault.c \
|
||||
mifare/mifarehost.c \
|
||||
mifare/gen4.c \
|
||||
nfc/ndef.c \
|
||||
pm3.c \
|
||||
pm3_binlib.c \
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include "cmdhw.h" // set_fpga_mode
|
||||
#include "loclass/cipherutils.h" // BitstreamOut_t
|
||||
#include "proxendian.h"
|
||||
#include "mifare/gen4.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
|
197
client/src/mifare/gen4.c
Normal file
197
client/src/mifare/gen4.c
Normal file
|
@ -0,0 +1,197 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Common functionality for low/high-frequency GALLAGHER tag encoding & decoding.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "gen4.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "commonutil.h"
|
||||
#include "util.h"
|
||||
#include "ui.h"
|
||||
#include "mifaredefault.h"
|
||||
#include "comms.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "protocols.h"
|
||||
#include "mfkey.h"
|
||||
#include "util_posix.h"
|
||||
#include "cmdparser.h"
|
||||
|
||||
static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen, bool verbose) {
|
||||
struct p {
|
||||
uint8_t cmdheader;
|
||||
uint8_t pwd[4];
|
||||
uint8_t command;
|
||||
uint8_t data[32];
|
||||
} PACKED payload;
|
||||
memset(&payload, 0, sizeof(payload));
|
||||
|
||||
if (datalen > sizeof(payload.data)) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
payload.cmdheader = 0xCF;
|
||||
payload.command = cmd;
|
||||
if (pwd != NULL) {
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
}
|
||||
if (data != NULL && datalen > 0) {
|
||||
memcpy(payload.data, data, datalen);
|
||||
}
|
||||
|
||||
int resplen = 0;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_RAW | ISO14A_NO_RATS | ISO14A_APPEND_CRC, 6 + datalen, 0, (uint8_t *)&payload, 6 + datalen);
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if (resp.oldarg[0] != 2) {
|
||||
if (verbose) PrintAndLogEx(ERR, "No card in the field.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||
}
|
||||
} else {
|
||||
if (verbose) PrintAndLogEx(ERR, "No card in the field.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
resplen = resp.oldarg[0];
|
||||
|
||||
if (!resplen) {
|
||||
if (verbose) PrintAndLogEx(ERR, "No card response.");
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
resplen = resplen - 2; // 14A CRC
|
||||
if (resplen < 0)
|
||||
resplen = 0;
|
||||
|
||||
if (resplen > 40) {
|
||||
if (verbose) PrintAndLogEx(ERR, "Buffer too small(%d).", resplen);
|
||||
return PM3_EOVFLOW;
|
||||
}
|
||||
|
||||
if (response != NULL)
|
||||
memcpy(response, resp.data.asBytes, resplen);
|
||||
|
||||
if (responselen != NULL)
|
||||
*responselen = resplen;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
} else {
|
||||
if (verbose) PrintAndLogEx(ERR, "Reply timeout.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
|
||||
uint8_t resp[40] = {0};
|
||||
size_t resplen = 0;
|
||||
|
||||
int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(data, resp, resplen);
|
||||
|
||||
if (datalen != NULL)
|
||||
*datalen = resplen;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
|
||||
uint8_t resp[40] = {0};
|
||||
size_t resplen = 0;
|
||||
|
||||
int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(data, resp, resplen);
|
||||
|
||||
if (datalen != NULL)
|
||||
*datalen = resplen;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
uint8_t workFlags;
|
||||
} PACKED payload;
|
||||
payload.blockno = blockno;
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
payload.workFlags = workFlags;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
uint8_t data[MFBLOCK_SIZE];
|
||||
uint8_t workFlags;
|
||||
} PACKED payload;
|
||||
payload.blockno = blockno;
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
memcpy(payload.data, data, sizeof(payload.data));
|
||||
payload.workFlags = workFlags;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_G4_WRBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_WRBL, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
#ifndef __GEN4_H
|
||||
#define __GEN4_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#define GEN4_CMD_CONFIG_GTU 0x32
|
||||
#define GEN4_CMD_CONFIG_ATS 0x34
|
||||
#define GEN4_CMD_CONFIG_ATQA_SAK 0x35
|
||||
|
@ -34,4 +36,10 @@
|
|||
#define GEN4_CMD_SET_CONFIG_PERMANENT 0xF1
|
||||
#define GEN4_CMD_CHANGE_PASSWORD 0xFE
|
||||
|
||||
int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose);
|
||||
int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose);
|
||||
|
||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
||||
int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1175,170 +1175,6 @@ int mfGen3Freeze(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static int mfG4ExCommand(uint8_t cmd, uint8_t *pwd, uint8_t *data, size_t datalen, uint8_t *response, size_t *responselen, bool verbose) {
|
||||
struct p {
|
||||
uint8_t cmdheader;
|
||||
uint8_t pwd[4];
|
||||
uint8_t command;
|
||||
uint8_t data[32];
|
||||
} PACKED payload;
|
||||
memset(&payload, 0, sizeof(payload));
|
||||
|
||||
if (datalen > sizeof(payload.data)) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
payload.cmdheader = 0xCF;
|
||||
payload.command = cmd;
|
||||
if (pwd != NULL) {
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
}
|
||||
if (data != NULL && datalen > 0) {
|
||||
memcpy(payload.data, data, datalen);
|
||||
}
|
||||
|
||||
int resplen = 0;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_RAW | ISO14A_NO_RATS | ISO14A_APPEND_CRC, 6 + datalen, 0, (uint8_t *)&payload, 6 + datalen);
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
if (resp.oldarg[0] != 2) {
|
||||
if (verbose) PrintAndLogEx(ERR, "No card in the field.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
iso14a_card_select_t card;
|
||||
memcpy(&card, (iso14a_card_select_t *)resp.data.asBytes, sizeof(iso14a_card_select_t));
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen));
|
||||
PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02X %02X"), card.atqa[1], card.atqa[0]);
|
||||
PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02X [%" PRIu64 "]"), card.sak, resp.oldarg[0]);
|
||||
}
|
||||
} else {
|
||||
if (verbose) PrintAndLogEx(ERR, "No card in the field.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) {
|
||||
resplen = resp.oldarg[0];
|
||||
|
||||
if (!resplen) {
|
||||
if (verbose) PrintAndLogEx(ERR, "No card response.");
|
||||
return PM3_EFAILED;
|
||||
}
|
||||
|
||||
resplen = resplen - 2; // 14A CRC
|
||||
if (resplen < 0)
|
||||
resplen = 0;
|
||||
|
||||
if (resplen > 40) {
|
||||
if (verbose) PrintAndLogEx(ERR, "Buffer too small(%d).", resplen);
|
||||
return PM3_EOVFLOW;
|
||||
}
|
||||
|
||||
if (response != NULL)
|
||||
memcpy(response, resp.data.asBytes, resplen);
|
||||
|
||||
if (responselen != NULL)
|
||||
*responselen = resplen;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
} else {
|
||||
if (verbose) PrintAndLogEx(ERR, "Reply timeout.");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
|
||||
uint8_t resp[40] = {0};
|
||||
size_t resplen = 0;
|
||||
|
||||
int res = mfG4ExCommand(GEN4_CMD_DUMP_CONFIG, pwd, NULL, 0, resp, &resplen, verbose);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(data, resp, resplen);
|
||||
|
||||
if (datalen != NULL)
|
||||
*datalen = resplen;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose) {
|
||||
uint8_t resp[40] = {0};
|
||||
size_t resplen = 0;
|
||||
|
||||
int res = mfG4ExCommand(GEN4_CMD_FACTORY_TEST, pwd, NULL, 0, resp, &resplen, verbose);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (data != NULL)
|
||||
memcpy(data, resp, resplen);
|
||||
|
||||
if (datalen != NULL)
|
||||
*datalen = resplen;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
uint8_t workFlags;
|
||||
} PACKED payload;
|
||||
payload.blockno = blockno;
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
payload.workFlags = workFlags;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_G4_RDBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_RDBL, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
memcpy(data, resp.data.asBytes, MFBLOCK_SIZE);
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags) {
|
||||
struct p {
|
||||
uint8_t blockno;
|
||||
uint8_t pwd[4];
|
||||
uint8_t data[MFBLOCK_SIZE];
|
||||
uint8_t workFlags;
|
||||
} PACKED payload;
|
||||
payload.blockno = blockno;
|
||||
memcpy(payload.pwd, pwd, sizeof(payload.pwd));
|
||||
memcpy(payload.data, data, sizeof(payload.data));
|
||||
payload.workFlags = workFlags;
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_MIFARE_G4_WRBL, (uint8_t *)&payload, sizeof(payload));
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_MIFARE_G4_WRBL, &resp, 1500)) {
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return PM3_EUNDEF;
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// variables
|
||||
uint32_t cuid = 0; // uid part used for crypto1.
|
||||
|
||||
|
|
|
@ -96,12 +96,6 @@ int mfGen3UID(uint8_t *uid, uint8_t uidlen, uint8_t *oldUid);
|
|||
int mfGen3Block(uint8_t *block, int blockLen, uint8_t *newBlock);
|
||||
int mfGen3Freeze(void);
|
||||
|
||||
int mfG4GetConfig(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose);
|
||||
int mfG4GetFactoryTest(uint8_t *pwd, uint8_t *data, size_t *datalen, bool verbose);
|
||||
|
||||
int mfG4GetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
||||
int mfG4SetBlock(uint8_t *pwd, uint8_t blockno, uint8_t *data, uint8_t workFlags);
|
||||
|
||||
int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
|
||||
|
||||
int detect_classic_prng(void);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue