From 77624fe57ead33b85519943d5122e6f402ad75ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 17 Oct 2025 13:34:04 +0200 Subject: [PATCH] add UL_AES CMAC secure messaging to `hf 14a raw`. Remember use `hf mfu aesauth -k --schann --key` before in order to authenticate and keep field up. After that you can use it with `hf 14a raw -c --schann 60` - to GET_VERSION --- armsrc/iso14443a.c | 20 +++++++++++++++++++- client/src/cmdhf14a.c | 19 ++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 8c3bbc755..ba0196ce9 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -37,6 +37,7 @@ #include "generator.h" #include "desfire_crypto.h" // UL-C authentication helpers #include "mifare.h" // for iso14a_polling_frame_t structure +#include "cmac_calc.h" #define MAX_ISO14A_TIMEOUT 524288 // this timeout is in MS @@ -3658,9 +3659,21 @@ void ReaderIso14443a(PacketCommandNG *c) { goto CMD_DONE; } } + + if ((param & ISO14A_APPEND_CMAC) == ISO14A_APPEND_CMAC) { + + if (len) { + // calc and append CMAC + append_cmac(cmd, len); + + len += 8; + // we skip lenbits since short 7bit commands is not in Ul-AES command set + } + } + if ((param & ISO14A_APPEND_CRC) == ISO14A_APPEND_CRC) { // Don't append crc on empty bytearray... - if (len > 0) { + if (len) { if ((param & ISO14A_TOPAZMODE) == ISO14A_TOPAZMODE) { AddCrc14B(cmd, len); @@ -3750,6 +3763,10 @@ void ReaderIso14443a(PacketCommandNG *c) { if ((param & ISO14A_CRYPTO1MODE) == ISO14A_CRYPTO1MODE) { mf_crypto1_decrypt(&crypto1_state, buf, arg0); } + + if ((param & ISO14A_APPEND_CMAC) == ISO14A_APPEND_CMAC) { + increase_session_counter(); + } FpgaDisableTracing(); reply_mix(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); } @@ -3769,6 +3786,7 @@ CMD_DONE: } OUT: + crypto1_auth_state = AUTH_FIRST; hf_field_off(); set_tracing(false); diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 014a7cb8e..1d50bf0e5 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -44,7 +44,7 @@ #include "mifare/mifaredefault.h" #include "preferences.h" // get/set device debug level #include "pm3_cmd.h" - +#include "mbedtls/cmac.h" static bool g_apdu_in_framing_enable = true; bool Get_apdu_in_framing(void) { @@ -1567,6 +1567,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) { arg_int0("w", "wait", "", "Wait in microseconds between select and command"), arg_lit0(NULL, "topaz", "Use Topaz protocol to send command"), arg_lit0(NULL, "crypto1", "Use crypto1 session"), + arg_lit0(NULL, "schann", "use secure channel. Must have key"), arg_strx1(NULL, NULL, "", "Raw bytes to send"), arg_param_end }; @@ -1584,10 +1585,11 @@ static int CmdHF14ACmdRaw(const char *Cmd) { uint32_t wait_us = (uint32_t)arg_get_int_def(ctx, 10, 0); bool topazmode = arg_get_lit(ctx, 11); bool crypto1mode = arg_get_lit(ctx, 12); + bool use_schann = 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; @@ -1600,6 +1602,18 @@ static int CmdHF14ACmdRaw(const char *Cmd) { } } + uint32_t flags = 0; + + if (use_schann) { + flags |= ISO14A_APPEND_CMAC; + + // Can't precalculate crc client side since we are adding cmac on device side. + if (crc) { + flags |= ISO14A_APPEND_CRC; + crc = false; + } + } + if (crc && datalen > 0 && datalen < sizeof(data) - 2) { uint8_t first, second; if (topazmode) { @@ -1611,7 +1625,6 @@ static int CmdHF14ACmdRaw(const char *Cmd) { data[datalen++] = second; } - uint16_t flags = 0; if (active || active_select) { flags |= ISO14A_CONNECT; if (active)