Skip to content

Commit

Permalink
Add crypto1 support to hf 14a raw
Browse files Browse the repository at this point in the history
  • Loading branch information
doegox committed Sep 26, 2024
1 parent 9a6f613 commit 2eac541
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 12 deletions.
9 changes: 5 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,17 @@ 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...

## [unreleased][unreleased]
- Print LUA and Python versions in `hw version` command (@jmichelp)
- Added crypto1 support to `hf 14a raw` (@doegox)
- Changed `hw version` command to print LUA and Python versions (@jmichelp)
- Updated LUA to v5.4.7 which adds utf-8 support (@jmichelp)
- Changed `lf search` - it now tries to read and decode paxton id (@iceman1001)
- Changed `lf search` - to identify hitag2/s/82xx in chipset detection to preserve their EM4100 or other outputs (@iceman1001)
- Added `lf hitag hts reader` - to act as a HitagS / 82xx reader (@iceman1001)
- Changed `lf hitag hts write` -> ´lf hitag hts wdbl` to fit rest of client command names (@iceman1001)
- Changed `lf hitag hts read` -> ´lf hitag hts rdbl` to fit rest of client command names (@iceman1001)
- Changed `lf hitag hts write` -> `lf hitag hts wdbl` to fit rest of client command names (@iceman1001)
- Changed `lf hitag hts read` -> `lf hitag hts rdbl` to fit rest of client command names (@iceman1001)
- Changed `hf mf info` - Better handling when printing ATS (@iceman1001)
- Changed to also try the MFC_B key when extracting memory (@iceman1001)
- Fix parallel `make -j check` Thanks @elboulangero (@iceman1001)
- Fixed parallel `make -j check` Thanks @elboulangero (@iceman1001)
- Added support for 8268/8310 (@douniwan5788)
- Changed scripting string params to accept 1024 chars, Thanks @evildaemond! (@iceman1001)
- Added detection for FM11NT021 (@iceman1001)
Expand Down
44 changes: 39 additions & 5 deletions armsrc/iso14443a.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,11 @@ iso14a_polling_parameters_t REQA_POLLING_PARAMETERS = {
// parity isn't used much
static uint8_t parity_array[MAX_PARITY_SIZE] = {0};

// crypto1 stuff
static uint8_t crypto1_auth_state = AUTH_FIRST;
static uint32_t crypto1_uid;
struct Crypto1State crypto1_state = {0, 0};

void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config"));
Dbprintf(" [a] Anticol override.... %s%s%s",
Expand Down Expand Up @@ -3151,14 +3156,14 @@ void ReaderIso14443a(PacketCommandNG *c) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);

// notify client selecting status.
// if failed selecting, turn off antenna and quite.
// if failed selecting, turn off antenna and quit.
if ((param & ISO14A_NO_SELECT) != ISO14A_NO_SELECT) {
iso14a_card_select_t *card = (iso14a_card_select_t *)buf;

arg0 = iso14443a_select_cardEx(
NULL,
card,
NULL,
&crypto1_uid,
true,
0,
((param & ISO14A_NO_RATS) == ISO14A_NO_RATS),
Expand All @@ -3167,6 +3172,11 @@ void ReaderIso14443a(PacketCommandNG *c) {
// TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params
FpgaDisableTracing();

if ((param & ISO14A_CRYPTO1MODE) == ISO14A_CRYPTO1MODE) {
crypto1_auth_state = AUTH_FIRST;
crypto1_deinit(&crypto1_state);
}

reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
if (arg0 == 0) {
goto OUT;
Expand Down Expand Up @@ -3195,7 +3205,20 @@ void ReaderIso14443a(PacketCommandNG *c) {
}

if ((param & ISO14A_RAW) == ISO14A_RAW) {

if ((param & ISO14A_CRYPTO1MODE) == ISO14A_CRYPTO1MODE) {
// Intercept special Auth command 6xxx<key>CRCA
if ((len == 10) && ((cmd[0] & 0xF0) == 0x60)) {
uint64_t ui64key = bytes_to_num((uint8_t *)&cmd[2], 6);
if (mifare_classic_authex_cmd(&crypto1_state, crypto1_uid, cmd[1], cmd[0], ui64key, crypto1_auth_state, NULL, NULL, NULL, NULL, false, false)) {
if (g_dbglevel >= DBG_INFO) Dbprintf("Auth error");
} else {
crypto1_auth_state = AUTH_NESTED;
if (g_dbglevel >= DBG_INFO) Dbprintf("Auth succeeded");
}
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
goto CMD_DONE;
}
}
if ((param & ISO14A_APPEND_CRC) == ISO14A_APPEND_CRC) {
// Don't append crc on empty bytearray...
if (len > 0) {
Expand All @@ -3213,7 +3236,10 @@ void ReaderIso14443a(PacketCommandNG *c) {
}
}
}

if ((param & ISO14A_CRYPTO1MODE) == ISO14A_CRYPTO1MODE) {
// Force explicit parity
lenbits = len * 8;
}
// want to send a specific number of bits (e.g. short commands)
if (lenbits > 0) {

Expand All @@ -3232,6 +3258,9 @@ void ReaderIso14443a(PacketCommandNG *c) {

} else {
GetParity(cmd, lenbits / 8, parity_array);
if ((param & ISO14A_CRYPTO1MODE) == ISO14A_CRYPTO1MODE) {
mf_crypto1_encrypt(&crypto1_state, cmd, len, parity_array);
}
ReaderTransmitBitsPar(cmd, lenbits, parity_array, NULL); // bytes are 8 bit with odd parity
}

Expand Down Expand Up @@ -3278,12 +3307,16 @@ void ReaderIso14443a(PacketCommandNG *c) {
reply_mix(CMD_ACK, 0, 0, 0, NULL, 0);
} else {
arg0 = ReaderReceive(buf, sizeof(buf), parity_array);

if ((param & ISO14A_CRYPTO1MODE) == ISO14A_CRYPTO1MODE) {
mf_crypto1_decrypt(&crypto1_state, buf, arg0);
}
FpgaDisableTracing();
reply_mix(CMD_ACK, arg0, 0, 0, buf, sizeof(buf));
}
}
}

CMD_DONE:
if ((param & ISO14A_REQUEST_TRIGGER) == ISO14A_REQUEST_TRIGGER)
iso14a_set_trigger(false);

Expand All @@ -3296,6 +3329,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
}

OUT:
crypto1_auth_state = AUTH_FIRST;
hf_field_off();
set_tracing(false);
}
Expand Down
19 changes: 17 additions & 2 deletions client/src/cmdhf14a.c
Original file line number Diff line number Diff line change
Expand Up @@ -1449,7 +1449,12 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
"Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
"hf 14a raw --ecp -s -> send ECP before select"
"hf 14a raw --ecp -s -> send ECP before select\n"
"Crypto1 session example, with special auth shortcut 6xxx<key>:\n"
"hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF\n"
"hf 14a raw --crypto1 -kc 3000\n"
"hf 14a raw --crypto1 -kc 6007FFFFFFFFFFFF\n"
"hf 14a raw --crypto1 -c 3007"
);

void *argtable[] = {
Expand All @@ -1466,6 +1471,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
arg_lit0(NULL, "ecp", "Use enhanced contactless polling"),
arg_lit0(NULL, "mag", "Use Apple magsafe polling"),
arg_lit0(NULL, "topaz", "Use Topaz protocol to send command"),
arg_lit0(NULL, "crypto1", "Use crypto1 session"),
arg_strx1(NULL, NULL, "<hex>", "Raw bytes to send"),
arg_param_end
};
Expand All @@ -1483,10 +1489,11 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
bool use_ecp = arg_get_lit(ctx, 10);
bool use_magsafe = arg_get_lit(ctx, 11);
bool topazmode = arg_get_lit(ctx, 12);
bool crypto1mode = arg_get_lit(ctx, 13);

int datalen = 0;
uint8_t data[PM3_CMD_DATA_SIZE_MIX] = {0};
CLIGetHexWithReturn(ctx, 13, data, &datalen);
CLIGetHexWithReturn(ctx, 14, data, &datalen);
CLIParserFree(ctx);

bool bTimeout = (timeout) ? true : false;
Expand Down Expand Up @@ -1540,6 +1547,14 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
flags |= ISO14A_TOPAZMODE;
}

if (crypto1mode) {
flags |= ISO14A_CRYPTO1MODE;
if (numbits > 0 || topazmode || use_ecp || use_magsafe) {
PrintAndLogEx(FAILED, "crypto1 mode cannot be used with other modes or partial bytes");
return PM3_EINVARG;
}
}

if (no_rats) {
flags |= ISO14A_NO_RATS;
}
Expand Down
3 changes: 2 additions & 1 deletion include/mifare.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@ typedef enum ISO14A_COMMAND {
ISO14A_SEND_CHAINING = (1 << 10),
ISO14A_USE_ECP = (1 << 11),
ISO14A_USE_MAGSAFE = (1 << 12),
ISO14A_USE_CUSTOM_POLLING = (1 << 13)
ISO14A_USE_CUSTOM_POLLING = (1 << 13),
ISO14A_CRYPTO1MODE = (1 << 14)
} iso14a_command_t;

// Defines a frame that will be used in a polling sequence
Expand Down

0 comments on commit 2eac541

Please sign in to comment.