diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index 2da553be8..fed515b37 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -352,7 +352,67 @@ static int em4x05_demod_resp(uint32_t *word, bool onlyPreamble) { return res; } + //////////////// 4205 / 4305 commands + +static bool em4x05_verify_write(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data) { + uint32_t r = 0; + int res = em4x05_read_word_ext(addr, pwd, use_pwd, &r); + if (res == PM3_SUCCESS) { + return (r == data); + } + return false; +} + +int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool use_pwd) { + + if (blockdata == NULL) + return PM3_EINVARG; + + if (numblocks < 1 || numblocks > 8) + return PM3_EINVARG; + + // fast push mode + conn.block_after_ACK = true; + + int res = em4x05_write_word_ext(EM_CONFIG_BLOCK, pwd, use_pwd, blockdata[0]); + if (res != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "(em4x05_clone_tag) Time out writing to tag"); + return res; + } + + for (int8_t i = 1; i < numblocks; i++) { + + // Disable fast mode on last packet + if (i == numblocks - 1) { + conn.block_after_ACK = false; + } + + res = em4x05_write_word_ext(4 + i, pwd, use_pwd, blockdata[i]); + if (res != PM3_SUCCESS) { + PrintAndLogEx(FAILED, "(em4x05_clone_tag) Time out writing to tag"); + return res; + } + } + + res = 0; + if (em4x05_verify_write(EM_CONFIG_BLOCK, use_pwd, pwd, blockdata[0]) == false) { + res++; + } + + for (int8_t i = 1; i < numblocks; i++) { + if (em4x05_verify_write(4 + i, use_pwd, pwd, blockdata[i]) == false) { + res++; + } + } + + if (res == 0) { + PrintAndLogEx(SUCCESS, "Success writing to tag"); + } + + return PM3_SUCCESS; +} + static int em4x05_login_ext(uint32_t pwd) { struct { @@ -376,7 +436,7 @@ static int em4x05_login_ext(uint32_t pwd) { return em4x05_demod_resp(&word, true); } -int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) { +int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t *word) { struct { uint32_t password; @@ -386,7 +446,7 @@ int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word payload.password = pwd; payload.address = addr; - payload.usepwd = usePwd; + payload.usepwd = use_pwd; clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X_READWORD, (uint8_t *)&payload, sizeof(payload)); @@ -402,7 +462,7 @@ int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word return em4x05_demod_resp(word, false); } -int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t data) { +int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data) { struct { uint32_t password; uint32_t data; @@ -413,7 +473,7 @@ int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t data payload.password = pwd; payload.data = data; payload.address = addr; - payload.usepwd = usePwd; + payload.usepwd = use_pwd; clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X_WRITEWORD, (uint8_t *)&payload, sizeof(payload)); diff --git a/client/src/cmdlfem4x05.h b/client/src/cmdlfem4x05.h index c8c19a6ff..cf8d35d20 100644 --- a/client/src/cmdlfem4x05.h +++ b/client/src/cmdlfem4x05.h @@ -61,8 +61,9 @@ typedef enum { int CmdLFEM4X05(const char *Cmd); bool em4x05_isblock0(uint32_t *word); -int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word); -int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t data); +int em4x05_read_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t *word); +int em4x05_write_word_ext(uint8_t addr, uint32_t pwd, bool use_pwd, uint32_t data); +int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool use_pwd); int CmdEM4x05Demod(const char *Cmd); int CmdEM4x05Dump(const char *Cmd); diff --git a/client/src/cmdlfkeri.c b/client/src/cmdlfkeri.c index 396a4a79f..7260bc494 100644 --- a/client/src/cmdlfkeri.c +++ b/client/src/cmdlfkeri.c @@ -8,23 +8,21 @@ // PSK1, RF/128, RF/2, 64 bits long //----------------------------------------------------------------------------- #include "cmdlfkeri.h" - #include #include - #include #include - -#include "commonutil.h" // ARRAYLEN +#include "commonutil.h" // ARRAYLEN #include "cmdparser.h" // command_t #include "cliparser.h" #include "comms.h" #include "ui.h" #include "cmddata.h" #include "cmdlf.h" -#include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // preamble test -#include "cmdlft55xx.h" // verifywrite +#include "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // preamble test +#include "cmdlft55xx.h" // verifywrite +#include "cmdlfem4x05.h" // static int CmdHelp(const char *Cmd); typedef enum {Scramble = 0, Descramble = 1} KeriMSScramble_t; @@ -185,7 +183,7 @@ static int CmdKeriRead(const char *Cmd) { static int CmdKeriClone(const char *Cmd) { - bool q5 = false; + bool q5 = false, em4305 = false; uint8_t keritype[2] = {'i'}; // default to internalid int typeLen = 0; @@ -207,7 +205,7 @@ static int CmdKeriClone(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "lf keri clone", - "clone a KERI tag to a T55x7 or Q5/T5555 tag", + "clone a KERI tag to a T55x7, Q5/T5555 or EM4305 tag", "lf keri clone -t i --id 12345\n" "lf keri clone -t m --fc 6 --id 12345\n"); @@ -217,6 +215,7 @@ static int CmdKeriClone(const char *Cmd) { arg_str0("t", "type", "", "Type m - MS, i - Internal ID"), arg_int0(NULL, "fc", "", "Facility Code"), arg_int1(NULL, "id", "", "Keri ID"), + arg_lit0(NULL, "em4305", "specify writing to EM5405 tag"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -225,12 +224,22 @@ static int CmdKeriClone(const char *Cmd) { blocks[0] = T5555_FIXED | T5555_MODULATION_PSK1 | T5555_SET_BITRATE(32) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; q5 = true; } + if (arg_get_lit(ctx, 5)) { + blocks[0] = EM4305_KERI_CONFIG_BLOCK; + em4305 = true; + } + typeLen = sizeof(keritype); CLIGetStrWithReturn(ctx, 2, keritype, &typeLen); fc = arg_get_int_def(ctx, 3, 0); cid = arg_get_int_def(ctx, 4, 0); CLIParserFree(ctx); + + if (q5 && em4305) { + PrintAndLogEx(FAILED, "Can't specify both Q5 and EM4305 at the same time"); + return PM3_EINVARG; + } // Setup card data/build internal id switch (keritype[0]) { @@ -256,7 +265,13 @@ static int CmdKeriClone(const char *Cmd) { print_blocks(blocks, ARRAYLEN(blocks)); - int res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + int res; + if (em4305) { + res = em4x05_clone_tag(blocks, ARRAYLEN(blocks), 0, false); + } else { + res = clone_t55xx_tag(blocks, ARRAYLEN(blocks)); + } + PrintAndLogEx(SUCCESS, "Done"); PrintAndLogEx(HINT, "Hint: try " _YELLOW_("`lf keri read`") " to verify"); return res;