2013-03-01 01:04:23 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Copyright (C) 2012 Chalk <chalk.secu at gmail.com>
|
2015-10-08 05:00:46 +08:00
|
|
|
// 2015 Dake <thomas.cayrou at gmail.com>
|
|
|
|
|
2013-03-01 01:04:23 +08:00
|
|
|
// 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.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Low frequency PCF7931 commands
|
|
|
|
//-----------------------------------------------------------------------------
|
2019-08-08 22:57:33 +08:00
|
|
|
#include "cmdlfpcf7931.h"
|
|
|
|
|
2013-03-01 01:04:23 +08:00
|
|
|
#include <string.h>
|
2020-03-02 21:15:51 +08:00
|
|
|
#include <ctype.h>
|
2019-08-08 22:57:33 +08:00
|
|
|
|
|
|
|
#include "cmdparser.h" // command_t
|
|
|
|
#include "comms.h"
|
2013-03-01 01:04:23 +08:00
|
|
|
#include "ui.h"
|
|
|
|
|
|
|
|
static int CmdHelp(const char *Cmd);
|
|
|
|
|
2015-10-13 03:30:54 +08:00
|
|
|
#define PCF7931_DEFAULT_INITDELAY 17500
|
|
|
|
#define PCF7931_DEFAULT_OFFSET_WIDTH 0
|
|
|
|
#define PCF7931_DEFAULT_OFFSET_POSITION 0
|
|
|
|
|
|
|
|
// Default values - Configuration
|
|
|
|
struct pcf7931_config configPcf = {
|
2019-03-10 07:00:59 +08:00
|
|
|
{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
|
2019-03-10 06:35:06 +08:00
|
|
|
PCF7931_DEFAULT_INITDELAY,
|
|
|
|
PCF7931_DEFAULT_OFFSET_WIDTH,
|
|
|
|
PCF7931_DEFAULT_OFFSET_POSITION
|
2019-03-10 07:00:59 +08:00
|
|
|
};
|
2015-10-13 03:30:54 +08:00
|
|
|
|
|
|
|
// Resets the configuration settings to default values.
|
2019-03-10 18:20:22 +08:00
|
|
|
int pcf7931_resetConfig() {
|
2019-03-10 07:00:59 +08:00
|
|
|
memset(configPcf.Pwd, 0xFF, sizeof(configPcf.Pwd));
|
2019-03-10 06:35:06 +08:00
|
|
|
configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY;
|
|
|
|
configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH;
|
|
|
|
configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION;
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-13 03:30:54 +08:00
|
|
|
}
|
2015-10-08 05:00:46 +08:00
|
|
|
|
2019-03-10 18:20:22 +08:00
|
|
|
int pcf7931_printConfig() {
|
2019-03-10 07:00:59 +08:00
|
|
|
PrintAndLogEx(NORMAL, "Password (LSB first on bytes) : %s", sprint_hex(configPcf.Pwd, sizeof(configPcf.Pwd)));
|
2019-03-10 06:35:06 +08:00
|
|
|
PrintAndLogEx(NORMAL, "Tag initialization delay : %d us", configPcf.InitDelay);
|
|
|
|
PrintAndLogEx(NORMAL, "Offset low pulses width : %d us", configPcf.OffsetWidth);
|
|
|
|
PrintAndLogEx(NORMAL, "Offset low pulses position : %d us", configPcf.OffsetPosition);
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-13 03:30:54 +08:00
|
|
|
}
|
|
|
|
|
2019-04-10 19:06:05 +08:00
|
|
|
static int usage_pcf7931_read() {
|
2019-03-10 06:35:06 +08:00
|
|
|
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 read [h] ");
|
|
|
|
PrintAndLogEx(NORMAL, "This command tries to read a PCF7931 tag.");
|
|
|
|
PrintAndLogEx(NORMAL, "Options:");
|
|
|
|
PrintAndLogEx(NORMAL, " h This help");
|
|
|
|
PrintAndLogEx(NORMAL, "Examples:");
|
|
|
|
PrintAndLogEx(NORMAL, " lf pcf7931 read");
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-08 05:00:46 +08:00
|
|
|
}
|
|
|
|
|
2019-04-10 19:06:05 +08:00
|
|
|
static int usage_pcf7931_write() {
|
2019-03-10 06:35:06 +08:00
|
|
|
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 write [h] <block address> <byte address> <data>");
|
|
|
|
PrintAndLogEx(NORMAL, "This command tries to write a PCF7931 tag.");
|
|
|
|
PrintAndLogEx(NORMAL, "Options:");
|
|
|
|
PrintAndLogEx(NORMAL, " h This help");
|
|
|
|
PrintAndLogEx(NORMAL, " blockaddress Block to save [0-7]");
|
|
|
|
PrintAndLogEx(NORMAL, " byteaddress Index of byte inside block to write [0-15]");
|
|
|
|
PrintAndLogEx(NORMAL, " data one byte of data (hex)");
|
|
|
|
PrintAndLogEx(NORMAL, "Examples:");
|
|
|
|
PrintAndLogEx(NORMAL, " lf pcf7931 write 2 1 FF");
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-13 03:30:54 +08:00
|
|
|
}
|
|
|
|
|
2019-04-10 19:06:05 +08:00
|
|
|
static int usage_pcf7931_config() {
|
2019-03-10 06:35:06 +08:00
|
|
|
PrintAndLogEx(NORMAL, "Usage: lf pcf7931 config [h] [r] <pwd> <delay> <offset width> <offset position>");
|
|
|
|
PrintAndLogEx(NORMAL, "This command tries to set the configuration used with PCF7931 commands");
|
|
|
|
PrintAndLogEx(NORMAL, "The time offsets could be useful to correct slew rate generated by the antenna");
|
|
|
|
PrintAndLogEx(NORMAL, "Caling without some parameter will print the current configuration.");
|
|
|
|
PrintAndLogEx(NORMAL, "Options:");
|
|
|
|
PrintAndLogEx(NORMAL, " h This help");
|
|
|
|
PrintAndLogEx(NORMAL, " r Reset configuration to default values");
|
|
|
|
PrintAndLogEx(NORMAL, " pwd Password, hex, 7bytes, LSB-order");
|
|
|
|
PrintAndLogEx(NORMAL, " delay Tag initialization delay (in us) decimal");
|
|
|
|
PrintAndLogEx(NORMAL, " offset Low pulses width (in us) decimal");
|
|
|
|
PrintAndLogEx(NORMAL, " offset Low pulses position (in us) decimal");
|
|
|
|
PrintAndLogEx(NORMAL, "Examples:");
|
|
|
|
PrintAndLogEx(NORMAL, " lf pcf7931 config");
|
|
|
|
PrintAndLogEx(NORMAL, " lf pcf7931 config r");
|
|
|
|
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 20000");
|
|
|
|
PrintAndLogEx(NORMAL, " lf pcf7931 config 11223344556677 17500 -10 30");
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-13 03:30:54 +08:00
|
|
|
}
|
|
|
|
|
2019-04-12 08:07:11 +08:00
|
|
|
static int CmdLFPCF7931Read(const char *Cmd) {
|
2015-10-13 03:30:54 +08:00
|
|
|
|
2020-03-02 21:15:51 +08:00
|
|
|
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
|
|
|
if (ctmp == 'h') return usage_pcf7931_read();
|
2019-03-10 06:35:06 +08:00
|
|
|
|
2019-04-18 18:43:35 +08:00
|
|
|
PacketResponseNG resp;
|
2019-03-10 06:35:06 +08:00
|
|
|
clearCommandBuffer();
|
2019-08-04 01:17:00 +08:00
|
|
|
SendCommandNG(CMD_LF_PCF7931_READ, NULL, 0);
|
2019-03-10 07:00:59 +08:00
|
|
|
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) {
|
2019-03-10 06:35:06 +08:00
|
|
|
PrintAndLogEx(WARNING, "command execution time out");
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_ETIMEOUT;
|
2019-03-10 06:35:06 +08:00
|
|
|
}
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-08 05:00:46 +08:00
|
|
|
}
|
|
|
|
|
2019-04-12 08:07:11 +08:00
|
|
|
static int CmdLFPCF7931Config(const char *Cmd) {
|
2015-10-13 03:30:54 +08:00
|
|
|
|
2020-03-02 21:15:51 +08:00
|
|
|
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
2019-03-10 07:00:59 +08:00
|
|
|
if (ctmp == 0) return pcf7931_printConfig();
|
2020-03-02 21:15:51 +08:00
|
|
|
if (ctmp == 'h') return usage_pcf7931_config();
|
|
|
|
if (ctmp == 'r') return pcf7931_resetConfig();
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2019-03-10 07:00:59 +08:00
|
|
|
if (param_gethex(Cmd, 0, configPcf.Pwd, 14)) return usage_pcf7931_config();
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2019-03-10 07:00:59 +08:00
|
|
|
configPcf.InitDelay = (param_get32ex(Cmd, 1, 0, 10) & 0xFFFF);
|
|
|
|
configPcf.OffsetWidth = (int)(param_get32ex(Cmd, 2, 0, 10) & 0xFFFF);
|
|
|
|
configPcf.OffsetPosition = (int)(param_get32ex(Cmd, 3, 0, 10) & 0xFFFF);
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2019-03-10 06:35:06 +08:00
|
|
|
pcf7931_printConfig();
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2015-10-08 05:00:46 +08:00
|
|
|
}
|
|
|
|
|
2019-04-12 08:07:11 +08:00
|
|
|
static int CmdLFPCF7931Write(const char *Cmd) {
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2020-03-02 21:15:51 +08:00
|
|
|
uint8_t ctmp = tolower(param_getchar(Cmd, 0));
|
|
|
|
if (strlen(Cmd) < 1 || ctmp == 'h') return usage_pcf7931_write();
|
2015-10-08 05:00:46 +08:00
|
|
|
|
2019-03-10 06:35:06 +08:00
|
|
|
uint8_t block = 0, bytepos = 0, data = 0;
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2019-03-10 07:00:59 +08:00
|
|
|
if (param_getdec(Cmd, 0, &block)) return usage_pcf7931_write();
|
|
|
|
if (param_getdec(Cmd, 1, &bytepos)) return usage_pcf7931_write();
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2019-03-10 07:00:59 +08:00
|
|
|
if ((block > 7) || (bytepos > 15)) return usage_pcf7931_write();
|
2015-10-13 03:30:54 +08:00
|
|
|
|
2019-03-10 06:35:06 +08:00
|
|
|
data = param_get8ex(Cmd, 2, 0, 16);
|
2019-03-09 15:59:13 +08:00
|
|
|
|
2020-03-02 21:15:51 +08:00
|
|
|
PrintAndLogEx(INFO, "Writing block: %d", block);
|
|
|
|
PrintAndLogEx(INFO, " pos: %d", bytepos);
|
|
|
|
PrintAndLogEx(INFO, " data: 0x%02X", data);
|
2015-10-08 05:00:46 +08:00
|
|
|
|
2019-04-19 23:03:39 +08:00
|
|
|
uint32_t buf[10]; // TODO sparse struct, 7 *bytes* then words at offset 4*7!
|
|
|
|
memcpy(buf, configPcf.Pwd, sizeof(configPcf.Pwd));
|
|
|
|
buf[7] = (configPcf.OffsetWidth + 128);
|
|
|
|
buf[8] = (configPcf.OffsetPosition + 128);
|
|
|
|
buf[9] = configPcf.InitDelay;
|
2015-10-08 05:00:46 +08:00
|
|
|
|
2019-03-10 06:35:06 +08:00
|
|
|
clearCommandBuffer();
|
2020-03-02 21:15:51 +08:00
|
|
|
SendCommandMIX(CMD_LF_PCF7931_WRITE, block, bytepos, data, buf, sizeof(buf));
|
|
|
|
|
|
|
|
PrintAndLogEx(SUCCESS, "Done");
|
2020-03-15 20:28:39 +08:00
|
|
|
PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf pcf7931 read`") "to verify");
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2013-03-01 01:04:23 +08:00
|
|
|
}
|
|
|
|
|
2017-07-30 15:17:48 +08:00
|
|
|
static command_t CommandTable[] = {
|
2019-05-02 02:48:15 +08:00
|
|
|
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
2019-05-02 06:02:38 +08:00
|
|
|
{"read", CmdLFPCF7931Read, IfPm3Lf, "Read content of a PCF7931 transponder"},
|
|
|
|
{"write", CmdLFPCF7931Write, IfPm3Lf, "Write data on a PCF7931 transponder."},
|
2019-05-02 02:48:15 +08:00
|
|
|
{"config", CmdLFPCF7931Config, AlwaysAvailable, "Configure the password, the tags initialization delay and time offsets (optional)"},
|
|
|
|
{NULL, NULL, NULL, NULL}
|
2013-03-01 01:04:23 +08:00
|
|
|
};
|
|
|
|
|
2019-04-12 08:07:11 +08:00
|
|
|
static int CmdHelp(const char *Cmd) {
|
|
|
|
(void)Cmd; // Cmd is not used so far
|
|
|
|
CmdsHelp(CommandTable);
|
2020-03-02 21:15:51 +08:00
|
|
|
return PM3_SUCCESS;
|
2019-04-12 08:07:11 +08:00
|
|
|
}
|
|
|
|
|
2019-03-10 18:20:22 +08:00
|
|
|
int CmdLFPCF7931(const char *Cmd) {
|
2019-03-10 06:35:06 +08:00
|
|
|
clearCommandBuffer();
|
2019-04-19 06:47:51 +08:00
|
|
|
return CmdsParse(CommandTable, Cmd);
|
2013-03-01 01:04:23 +08:00
|
|
|
}
|
|
|
|
|