diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index 2c6ace8ee..482d126a4 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -954,6 +954,16 @@ static void PacketReceived(PacketCommandNG *packet) {
EM4xWriteWord(payload->address, payload->data, payload->password, payload->usepwd);
break;
}
+ case CMD_LF_EM4X_PROTECTWORD: {
+ struct p {
+ uint32_t password;
+ uint32_t data;
+ uint8_t usepwd;
+ } PACKED;
+ struct p *payload = (struct p *) packet->data.asBytes;
+ EM4xProtectWord(payload->data, payload->password, payload->usepwd);
+ break;
+ }
case CMD_LF_AWID_WATCH: {
uint32_t high, low;
int res = lf_awid_watch(0, &high, &low);
diff --git a/armsrc/lfops.c b/armsrc/lfops.c
index b68e54bbc..b2126fc76 100644
--- a/armsrc/lfops.c
+++ b/armsrc/lfops.c
@@ -2369,6 +2369,7 @@ int copy_em410x_to_t55xx(uint8_t card, uint8_t clock, uint32_t id_hi, uint32_t i
#define FWD_CMD_LOGIN 0xC
#define FWD_CMD_WRITE 0xA
#define FWD_CMD_READ 0x9
+#define FWD_CMD_PROTECT 0x3
#define FWD_CMD_DISABLE 0x5
static uint8_t forwardLink_data[64]; //array of forwarded bits
@@ -2573,9 +2574,9 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
SendForward(len);
// Wait 20ms for write to complete?
- WaitMS(7);
+ WaitUS(10820); // tPC+tWEE
- DoPartialAcquisition(20, false, 6000, 1000);
+ DoPartialAcquisition(0, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@@ -2583,6 +2584,42 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
LEDsoff();
}
+void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd) {
+
+ StartTicks();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ WaitMS(50);
+
+ LED_A_ON();
+
+ // clear buffer now so it does not interfere with timing later
+ BigBuf_Clear_ext(false);
+
+ /* should we read answer from Logincommand?
+ *
+ * should receive
+ * 0000 1010 ok.
+ * 0000 0001 fail
+ **/
+ if (usepwd) EM4xLogin(pwd);
+
+ forward_ptr = forwardLink_data;
+ uint8_t len = Prepare_Cmd(FWD_CMD_PROTECT);
+ len += Prepare_Data(data & 0xFFFF, data >> 16);
+
+ SendForward(len);
+
+ // Wait 20ms for write to complete?
+ WaitUS(13640); // tPC+tPR
+
+ DoPartialAcquisition(0, false, 6000, 1000);
+
+ StopTicks();
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ reply_ng(CMD_LF_EM4X_PROTECTWORD, PM3_SUCCESS, NULL, 0);
+ LEDsoff();
+}
+
/*
Reading COTAG.
diff --git a/armsrc/lfops.h b/armsrc/lfops.h
index 0ac8066af..1c191d65d 100644
--- a/armsrc/lfops.h
+++ b/armsrc/lfops.h
@@ -58,6 +58,7 @@ void TurnReadLFOn(uint32_t delay);
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
+void EM4xProtectWord(uint32_t data, uint32_t pwd, uint8_t usepwd);
void Cotag(uint32_t arg0);
void setT55xxConfig(uint8_t arg0, t55xx_configurations_t *c);
diff --git a/client/src/cmdlfem4x.c b/client/src/cmdlfem4x.c
index c26bd2602..aa15c1fe9 100644
--- a/client/src/cmdlfem4x.c
+++ b/client/src/cmdlfem4x.c
@@ -164,7 +164,7 @@ static int usage_lf_em4x05_write(void) {
PrintAndLogEx(NORMAL, "Usage: lf em 4x05_write [h]
");
PrintAndLogEx(NORMAL, "Options:");
PrintAndLogEx(NORMAL, " h - this help");
- PrintAndLogEx(NORMAL, " address - memory address to write to. (0-15)");
+ PrintAndLogEx(NORMAL, " address - memory address to write to. (0-13, 99 for Protection Words)");
PrintAndLogEx(NORMAL, " data - data to write (hex)");
PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)");
PrintAndLogEx(NORMAL, "Examples:");
@@ -857,7 +857,6 @@ static int demodEM4x05resp(uint32_t *word) {
*word = 0;
if (detectASK_MAN() && doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
-
if (detectASK_BI() && doPreambleSearch(&idx))
return setDemodBufferEM(word, idx);
@@ -1101,37 +1100,62 @@ static int CmdEM4x05Write(const char *Cmd) {
data = param_get32ex(Cmd, 1, 0, 16);
pwd = param_get32ex(Cmd, 2, 0xFFFFFFFF, 16);
- if (addr > 15) {
- PrintAndLogEx(NORMAL, "Address must be between 0 and 15");
+ if ((addr > 13) && (addr != 99)) {
+ PrintAndLogEx(NORMAL, "Address must be between 0 and 13");
return PM3_EINVARG;
}
- if (pwd == 0xFFFFFFFF)
- PrintAndLogEx(NORMAL, "Writing address %d data %08X", addr, data);
- else {
+ if (pwd == 0xFFFFFFFF) {
+ if (addr == 99)
+ PrintAndLogEx(NORMAL, "Writing protection words data %08X", addr, data);
+ else
+ PrintAndLogEx(NORMAL, "Writing address %d data %08X", addr, data);
+ } else {
usePwd = true;
- PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd);
+ if (addr == 99)
+ PrintAndLogEx(NORMAL, "Writing protection words data %08X using password %08X", addr, data, pwd);
+ else
+ PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd);
}
- struct {
- uint32_t password;
- uint32_t data;
- uint8_t address;
- uint8_t usepwd;
- } PACKED payload;
+ if (addr == 99) { // set Protect Words
+ struct {
+ uint32_t password;
+ uint32_t data;
+ uint8_t usepwd;
+ } PACKED payload;
- payload.password = pwd;
- payload.data = data;
- payload.address = addr;
- payload.usepwd = usePwd;
+ payload.password = pwd;
+ payload.data = data;
+ payload.usepwd = usePwd;
- clearCommandBuffer();
- SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload));
- PacketResponseNG resp;
- if (!WaitForResponseTimeout(CMD_LF_EM4X_WRITEWORD, &resp, 2000)) {
- PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
- return PM3_ETIMEOUT;
+ clearCommandBuffer();
+ SendCommandNG(CMD_LF_EM4X_PROTECTWORD, (uint8_t *)&payload, sizeof(payload));
+ PacketResponseNG resp;
+ if (!WaitForResponseTimeout(CMD_LF_EM4X_PROTECTWORD, &resp, 2000)) {
+ PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
+ return PM3_ETIMEOUT;
+ }
+ } else {
+ struct {
+ uint32_t password;
+ uint32_t data;
+ uint8_t address;
+ uint8_t usepwd;
+ } PACKED payload;
+
+ payload.password = pwd;
+ payload.data = data;
+ payload.address = addr;
+ payload.usepwd = usePwd;
+
+ clearCommandBuffer();
+ SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload));
+ PacketResponseNG resp;
+ if (!WaitForResponseTimeout(CMD_LF_EM4X_WRITEWORD, &resp, 2000)) {
+ PrintAndLogEx(ERR, "Error occurred, device did not respond during write operation.");
+ return PM3_ETIMEOUT;
+ }
}
-
if (!downloadSamplesEM())
return PM3_ENODATA;
diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h
index 6cacc5ef1..e96c58984 100644
--- a/include/pm3_cmd.h
+++ b/include/pm3_cmd.h
@@ -486,6 +486,7 @@ typedef struct {
#define CMD_LF_PCF7931_WRITE 0x0223
#define CMD_LF_EM4X_READWORD 0x0218
#define CMD_LF_EM4X_WRITEWORD 0x0219
+#define CMD_LF_EM4X_PROTECTWORD 0x021B
#define CMD_LF_IO_WATCH 0x021A
#define CMD_LF_EM410X_WATCH 0x021C
#define CMD_LF_EM4X50_INFO 0x0240