From be9db1885206cc1d3f41de75be8d373754f04de2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 15:22:33 +0300 Subject: [PATCH 1/7] fix coverity 350572 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index d141a22b8..f773b4268 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5198,7 +5198,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } From 7882a2dbaabed16d08b53a2e42ab8df091252195 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 19:03:41 +0300 Subject: [PATCH 2/7] fix coverity 350557 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index f773b4268..a20f196b4 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5297,7 +5297,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); for (int i = 0; i < buflen; i++) - PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%d]: %s", + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", DesfireAIDByteToUint(&buf[i * 24 + 1]), buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], strlen((char *)&buf[i * 24 + 1 + 5]), From b63a991bc3fe04bff44713cdf829edc893f639b8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 19:04:41 +0300 Subject: [PATCH 3/7] fix coverity 350561 --- client/src/cmdhfmfdes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index a20f196b4..085a85cff 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5278,7 +5278,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { if (DesfireIsAuthenticated(&dctx)) { if (verbose) - PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated") , res); + PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); } else { return PM3_ESOFT; } From d2491d342d05bb4fcf8f18329dd64a06f0b10d83 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 5 Jul 2021 19:31:42 +0300 Subject: [PATCH 4/7] move secure channel functions to separate file --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/mifare/desfirecore.c | 157 +--------------------- client/src/mifare/desfiresecurechan.c | 180 ++++++++++++++++++++++++++ client/src/mifare/desfiresecurechan.h | 27 ++++ 5 files changed, 210 insertions(+), 156 deletions(-) create mode 100644 client/src/mifare/desfiresecurechan.c create mode 100644 client/src/mifare/desfiresecurechan.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 0aa5f2dc3..4879e953b 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -226,6 +226,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/mifare/mifarehost.c ${PM3_ROOT}/client/src/nfc/ndef.c ${PM3_ROOT}/client/src/mifare/desfire_crypto.c + ${PM3_ROOT}/client/src/mifare/desfiresecurechan.c ${PM3_ROOT}/client/src/mifare/desfirecore.c ${PM3_ROOT}/client/src/uart/uart_posix.c ${PM3_ROOT}/client/src/uart/uart_win32.c diff --git a/client/Makefile b/client/Makefile index 9a2ef3c5c..45ddffe31 100644 --- a/client/Makefile +++ b/client/Makefile @@ -590,6 +590,7 @@ SRCS = aiddesfire.c \ loclass/ikeys.c \ mifare/desfire_crypto.c \ mifare/desfirecore.c \ + mifare/desfiresecurechan.c \ mifare/mad.c \ mifare/mfkey.c \ mifare/mifare4.c \ diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 9b80ede51..ef8830302 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -31,6 +31,7 @@ #include "iso7816/iso7816core.h" // APDU logging #include "util_posix.h" // msleep #include "mifare/desfire_crypto.h" +#include "desfiresecurechan.h" const CLIParserOption DesfireAlgoOpts[] = { {T_DES, "des"}, @@ -543,162 +544,6 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t return PM3_SUCCESS; } -static void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { - uint8_t data[1024] = {0}; - - switch(ctx->keyType) { - case T_DES: - if (ctx->secureChannel == DACd40) { - if (encode) - des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); - else - des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); - } if (ctx->secureChannel == DACEV1) { - if (encode) - des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - else - des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); - } - - if (dstdata) - memcpy(dstdata, data, srcdatalen); - break; - case T_3DES: - break; - case T_3K3DES: - break; - case T_AES: - if (encode) - aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - else - aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); - if (dstdata) - memcpy(dstdata, data, srcdatalen); - break; - } -} - -static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - uint8_t data[1024] = {0}; - size_t rlen = 0; - - switch(ctx->commMode) { - case DCMPlain: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - case DCMMACed: - if (srcdatalen == 0) - break; - - rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); - memcpy(data, srcdata, srcdatalen); - DesfireCryptoEncDec(ctx, data, rlen, NULL, true); - memcpy(dstdata, srcdata, srcdatalen); - memcpy(&dstdata[srcdatalen], ctx->IV, desfire_get_key_block_length(ctx->keyType)); - *dstdatalen = rlen; - break; - case DCMEncrypted: - rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 - memcpy(data, srcdata, srcdatalen); - compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); - DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); - *dstdatalen = rlen; - break; - case DCMNone:; - } -} - -static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch(ctx->commMode) { - case DCMPlain: - case DCMMACed: - - break; - case DCMEncrypted: - break; - case DCMNone:; - } -} - -static void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { - case DACd40: - DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); - break; - case DACEV1: - DesfireSecureChannelEncodeEV1(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); - break; - case DACEV2: - break; - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - -static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch(ctx->commMode) { - case DCMMACed: - - break; - case DCMEncrypted: - break; - case DCMPlain: - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - -static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch(ctx->commMode) { - case DCMPlain: - case DCMMACed: - memcpy(dstdata, srcdata, srcdatalen - 8); - *dstdatalen = srcdatalen - 8; - - break; - case DCMEncrypted: - break; - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - -static void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { - case DACd40: - DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); - break; - case DACEV1: - DesfireSecureChannelDecodeEV1(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); - break; - case DACEV2: - break; - case DACNone: - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - break; - } -} - // move data from blockdata [format: ...] to single data block static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) { *dstdatalen = 0; diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c new file mode 100644 index 000000000..1838a000a --- /dev/null +++ b/client/src/mifare/desfiresecurechan.c @@ -0,0 +1,180 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Romain Tartiere. +// Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok +// +// 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. +//----------------------------------------------------------------------------- +// High frequency Desfire secure channel functions +//----------------------------------------------------------------------------- + +#include "desfiresecurechan.h" + +#include +#include +#include +#include "ui.h" +#include "crc.h" +#include "crc16.h" // crc16 ccitt +#include "crc32.h" +#include "commonutil.h" +#include "mifare/desfire_crypto.h" + + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + uint8_t data[1024] = {0}; + + switch(ctx->keyType) { + case T_DES: + if (ctx->secureChannel == DACd40) { + if (encode) + des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); + else + des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); + } if (ctx->secureChannel == DACEV1) { + if (encode) + des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + else + des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); + } + + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + case T_3DES: + break; + case T_3K3DES: + break; + case T_AES: + if (encode) + aes_encode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + else + aes_decode(ctx->IV, ctx->key, srcdata, data, srcdatalen); + if (dstdata) + memcpy(dstdata, data, srcdatalen); + break; + } +} + +static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + uint8_t data[1024] = {0}; + size_t rlen = 0; + + switch(ctx->commMode) { + case DCMPlain: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + case DCMMACed: + if (srcdatalen == 0) + break; + + rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, srcdata, srcdatalen); + DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + memcpy(dstdata, srcdata, srcdatalen); + memcpy(&dstdata[srcdatalen], ctx->IV, 4); + *dstdatalen = rlen; + break; + case DCMEncrypted: + rlen = padded_data_length(srcdatalen + 2, desfire_get_key_block_length(ctx->keyType)); // 2 - crc16 + memcpy(data, srcdata, srcdatalen); + compute_crc(CRC_14443_A, data, srcdatalen, &data[srcdatalen], &data[srcdatalen + 1]); + DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); + *dstdatalen = rlen; + break; + case DCMNone:; + } +} + +static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMPlain: + case DCMMACed: + + break; + case DCMEncrypted: + break; + case DCMNone:; + } +} + +void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + switch(ctx->secureChannel) { + case DACd40: + DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; + case DACEV1: + DesfireSecureChannelEncodeEV1(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); + break; + case DACEV2: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMMACed: + + break; + case DCMEncrypted: + break; + case DCMPlain: + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + + switch(ctx->commMode) { + case DCMPlain: + case DCMMACed: + memcpy(dstdata, srcdata, srcdatalen - 8); + *dstdatalen = srcdatalen - 8; + + break; + case DCMEncrypted: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} + +void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { + switch(ctx->secureChannel) { + case DACd40: + DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; + case DACEV1: + DesfireSecureChannelDecodeEV1(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); + break; + case DACEV2: + break; + case DACNone: + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + break; + } +} diff --git a/client/src/mifare/desfiresecurechan.h b/client/src/mifare/desfiresecurechan.h new file mode 100644 index 000000000..df997eb54 --- /dev/null +++ b/client/src/mifare/desfiresecurechan.h @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2010 Romain Tartiere. +// Copyright (C) 2014 Iceman +// Copyright (C) 2021 Merlok +// +// 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. +//----------------------------------------------------------------------------- +// High frequency Desfire secure channel functions +//----------------------------------------------------------------------------- + +#ifndef __DESFIRESECURECHAN_H +#define __DESFIRESECURECHAN_H + +#include "common.h" +#include "mifare/desfirecore.h" +#include "mifare/desfire_crypto.h" +#include "mifare/mifare4.h" + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); + +void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen); +void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen); + + +#endif // __DESFIRESECURECHAN_H From 56d7efdbb5ac979f9bd73b54ae9457c97fe437f2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:05:38 +0300 Subject: [PATCH 5/7] move some functions from cipurse to libcrypto --- client/src/cipurse/cipursecrypto.c | 23 ----------------------- client/src/cipurse/cipursecrypto.h | 4 ---- client/src/cipurse/cipursetest.c | 1 + client/src/crypto/libpcrypto.c | 23 +++++++++++++++++++++++ client/src/crypto/libpcrypto.h | 7 +++++++ 5 files changed, 31 insertions(+), 27 deletions(-) diff --git a/client/src/cipurse/cipursecrypto.c b/client/src/cipurse/cipursecrypto.c index 9761fb1e3..cbf084ef4 100644 --- a/client/src/cipurse/cipursecrypto.c +++ b/client/src/cipurse/cipursecrypto.c @@ -40,11 +40,6 @@ uint8_t CipurseCSecurityLevelEnc(CipurseChannelSecurityLevel lvl) { } } -static void bin_xor(uint8_t *d1, uint8_t *d2, size_t len) { - for (size_t i = 0; i < len; i++) - d1[i] = d1[i] ^ d2[i]; -} - static void bin_ext(uint8_t *dst, size_t dstlen, uint8_t *src, size_t srclen) { if (srclen > dstlen) memcpy(dst, &src[srclen - dstlen], dstlen); @@ -218,24 +213,6 @@ bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT) { return (memcmp(CT, ctx->CT, CIPURSE_AES_KEY_LENGTH) == 0); } -void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen) { - *ddatalen = sdatalen + 1; - *ddatalen += blocklen - *ddatalen % blocklen; - memset(ddata, 0, *ddatalen); - memcpy(ddata, sdata, sdatalen); - ddata[sdatalen] = ISO9797_M2_PAD_BYTE; -} - -size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen) { - for (int i = datalen; i > 0; i--) { - if (data[i - 1] == 0x80) - return i - 1; - if (data[i - 1] != 0x00) - return 0; - } - return 0; -} - static uint16_t CipurseCComputeMICCRC(uint8_t *data, size_t len) { uint16_t initCRC = 0x6363; for (size_t i = 0; i < len; i++) { diff --git a/client/src/cipurse/cipursecrypto.h b/client/src/cipurse/cipursecrypto.h index 7790eb600..aba244830 100644 --- a/client/src/cipurse/cipursecrypto.h +++ b/client/src/cipurse/cipursecrypto.h @@ -21,7 +21,6 @@ #define CIPURSE_MAC_LENGTH 8 #define CIPURSE_MIC_LENGTH 4 #define CIPURSE_POLY 0x35b088cce172UL -#define ISO9797_M2_PAD_BYTE 0x80 #define member_size(type, member) sizeof(((type *)0)->member) @@ -66,9 +65,6 @@ bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT); void CipurseCChannelSetSecurityLevels(CipurseContext *ctx, CipurseChannelSecurityLevel req, CipurseChannelSecurityLevel resp); bool isCipurseCChannelSecuritySet(CipurseContext *ctx); -void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen); -size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen); - void CipurseCGenerateMAC(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); void CipurseCCalcMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); bool CipurseCCheckMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); diff --git a/client/src/cipurse/cipursetest.c b/client/src/cipurse/cipursetest.c index 6ccd4f91d..5de6be161 100644 --- a/client/src/cipurse/cipursetest.c +++ b/client/src/cipurse/cipursetest.c @@ -14,6 +14,7 @@ #include // memcpy memset #include "fileutils.h" +#include "crypto/libpcrypto.h" #include "cipurse/cipursecrypto.h" #include "cipurse/cipursecore.h" diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index af15c1f5e..32686b199 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -536,3 +536,26 @@ exit: PrintAndLogEx(NORMAL, _RED_("failed\n")); return res; } + +void bin_xor(uint8_t *d1, uint8_t *d2, size_t len) { + for (size_t i = 0; i < len; i++) + d1[i] = d1[i] ^ d2[i]; +} + +void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen) { + *ddatalen = sdatalen + 1; + *ddatalen += blocklen - *ddatalen % blocklen; + memset(ddata, 0, *ddatalen); + memcpy(ddata, sdata, sdatalen); + ddata[sdatalen] = ISO9797_M2_PAD_BYTE; +} + +size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen) { + for (int i = datalen; i > 0; i--) { + if (data[i - 1] == 0x80) + return i - 1; + if (data[i - 1] != 0x00) + return 0; + } + return 0; +} diff --git a/client/src/crypto/libpcrypto.h b/client/src/crypto/libpcrypto.h index d5f7b809b..3f3bdb45b 100644 --- a/client/src/crypto/libpcrypto.h +++ b/client/src/crypto/libpcrypto.h @@ -42,4 +42,11 @@ char *ecdsa_get_error(int ret); int ecdsa_nist_test(bool verbose); +void bin_xor(uint8_t *d1, uint8_t *d2, size_t len); + +#define ISO9797_M2_PAD_BYTE 0x80 +void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen); +size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen); + + #endif /* libpcrypto.h */ From 0a51eb445d3f93346de4aa6d059c1177fb0b8ad7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:05:59 +0300 Subject: [PATCH 6/7] add mac sketch --- client/src/mifare/desfiresecurechan.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 1838a000a..90aa643ce 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -22,7 +22,6 @@ #include "commonutil.h" #include "mifare/desfire_crypto.h" - void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { uint8_t data[1024] = {0}; @@ -93,13 +92,25 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint } static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + uint8_t data[1024] = {0}; + size_t rlen = 0; + memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; switch(ctx->commMode) { case DCMPlain: case DCMMACed: + data[0] = cmd; + rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); + memcpy(&data[1], srcdata, srcdatalen); + DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + memcpy(dstdata, srcdata, srcdatalen); + if (srcdatalen != 0 && ctx->commMode == DCMMACed) { + memcpy(&dstdata[srcdatalen], ctx->IV, 4); + *dstdatalen = rlen; + } break; case DCMEncrypted: break; From 20696fb44a408abe31e852129af3a4777632f886 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:16:19 +0300 Subject: [PATCH 7/7] make style --- client/deps/cliparser/cliparser.c | 16 +-- client/src/cmdhfemrtd.c | 4 +- client/src/cmdhfmfdes.c | 106 +++++++++--------- client/src/mifare/desfire_crypto.c | 14 ++- client/src/mifare/desfire_crypto.h | 4 +- client/src/mifare/desfirecore.c | 152 +++++++++++++------------- client/src/mifare/desfirecore.h | 6 +- client/src/mifare/desfiresecurechan.c | 39 ++++--- doc/commands.json | 102 +++++++++++++---- doc/commands.md | 3 + 10 files changed, 260 insertions(+), 186 deletions(-) diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index ad89856cd..93636a02b 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -304,13 +304,13 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array int res = CLIParamStrToBuf(argstr, (uint8_t *)data, sizeof(data), &datalen); if (res) return res; - + // no data to check - we do not touch *value, just return if (datalen == 0) return 0; - + str_lower(data); - + int val = -1; int cntr = 0; for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { @@ -328,7 +328,7 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array cntr++; } } - + // check partial match if (cntr == 0) { PrintAndLogEx(ERR, "Parameter error: No similar option to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); @@ -338,14 +338,14 @@ int CLIGetOptionList(struct arg_str *argstr, const CLIParserOption *option_array PrintAndLogEx(ERR, "Parameter error: Several options fit to `%s`. Valid options: %s\n", argstr->sval[0], argstr->hdr.datatype); return 21; } - - *value = val; - return 0; + + *value = val; + return 0; } const char *CLIGetOptionListStr(const CLIParserOption *option_array, int value) { static const char *errmsg = "n/a"; - + for (int i = 0; i < CLI_MAX_OPTLIST_LEN; i++) { if (option_array[i].text == NULL) break; diff --git a/client/src/cmdhfemrtd.c b/client/src/cmdhfemrtd.c index 2cda5e1da..d9f487ec8 100644 --- a/client/src/cmdhfemrtd.c +++ b/client/src/cmdhfemrtd.c @@ -1424,7 +1424,7 @@ static int emrtd_print_ef_dg2_info(uint8_t *data, size_t datalen) { bool is_jpg = (data[offset] == 0xFF); - char *fn = calloc( strlen(dg_table[EF_DG2].filename) + 4 + 1, sizeof(uint8_t)); + char *fn = calloc(strlen(dg_table[EF_DG2].filename) + 4 + 1, sizeof(uint8_t)); if (fn == NULL) return PM3_EMALLOC; @@ -1435,7 +1435,7 @@ static int emrtd_print_ef_dg2_info(uint8_t *data, size_t datalen) { char *path; if (searchHomeFilePath(&path, NULL, fn, false) != PM3_SUCCESS) { free(fn); - return PM3_EFILE; + return PM3_EFILE; } free(fn); diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 085a85cff..4204b8a3c 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -4998,23 +4998,23 @@ static int CmdHF14aDesMAD(const char *Cmd) { return PM3_SUCCESS; } */ -static uint8_t defaultKeyNum = 0; +static uint8_t defaultKeyNum = 0; static enum DESFIRE_CRYPTOALGO defaultAlgoId = T_DES; static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0}; static int defaultKdfAlgo = MFDES_KDF_ALGO_NONE; static int defaultKdfInputLen = 0; static uint8_t defaultKdfInput[50] = {0}; -static DesfireSecureChannel defaultSecureChannel = DACEV1; -static DesfireCommandSet defaultCommSet = DCCNativeISO; +static DesfireSecureChannel defaultSecureChannel = DACEV1; +static DesfireCommandSet defaultCommSet = DCCNativeISO; static DesfireCommunicationMode defaultCommMode = DCMPlain; -static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx, - uint8_t keynoid, uint8_t algoid, uint8_t keyid, - uint8_t kdfid, uint8_t kdfiid, - uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, - int *securechannel) { - - uint8_t keynum = defaultKeyNum; +static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx, + uint8_t keynoid, uint8_t algoid, uint8_t keyid, + uint8_t kdfid, uint8_t kdfiid, + uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid, + int *securechannel) { + + uint8_t keynum = defaultKeyNum; int algores = defaultAlgoId; uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0}; memcpy(key, defaultKey, DESFIRE_MAX_KEY_SIZE); @@ -5029,17 +5029,17 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (keynoid) { keynum = arg_get_int_def(ctx, keynoid, keynum); } - + if (algoid) { if (CLIGetOptionList(arg_get_str(ctx, algoid), DesfireAlgoOpts, &algores)) - return PM3_ESOFT; + return PM3_ESOFT; } - + if (keyid) { int keylen = 0; uint8_t keydata[200] = {0}; if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen)) - return PM3_ESOFT; + return PM3_ESOFT; if (keylen && keylen != desfire_get_key_length(algores)) { PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(DesfireAlgoOpts, algores), desfire_get_key_length(algores), keylen); return PM3_EINVARG; @@ -5047,45 +5047,45 @@ static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dct if (keylen) memcpy(key, keydata, keylen); } - + if (kdfid) { if (CLIGetOptionList(arg_get_str(ctx, kdfid), DesfireKDFAlgoOpts, &kdfAlgo)) - return PM3_ESOFT; + return PM3_ESOFT; } - + if (kdfiid) { int datalen = kdfInputLen; uint8_t data[200] = {0}; if (CLIParamHexToBuf(arg_get_str(ctx, kdfiid), data, sizeof(data), &datalen)) - return PM3_ESOFT; + return PM3_ESOFT; if (datalen) { kdfInputLen = datalen; memcpy(kdfInput, data, datalen); } } - + if (cmodeid) { if (CLIGetOptionList(arg_get_str(ctx, cmodeid), DesfireCommunicationModeOpts, &commmode)) - return PM3_ESOFT; + return PM3_ESOFT; } if (ccsetid) { if (CLIGetOptionList(arg_get_str(ctx, ccsetid), DesfireCommandSetOpts, &commset)) - return PM3_ESOFT; + return PM3_ESOFT; } if (schannid) { if (CLIGetOptionList(arg_get_str(ctx, schannid), DesfireSecureChannelOpts, &secchann)) - return PM3_ESOFT; + return PM3_ESOFT; } - + DesfireSetKey(dctx, keynum, algores, key); DesfireSetKdf(dctx, kdfAlgo, kdfInput, kdfInputLen); DesfireSetCommandSet(dctx, commset); DesfireSetCommMode(dctx, commmode); if (securechannel) *securechannel = secchann; - + return PM3_SUCCESS; } @@ -5116,17 +5116,17 @@ static int CmdHF14ADesDefault(const char *Cmd) { CLIParserFree(ctx); return res; } - + CLIParserFree(ctx); - - defaultKeyNum = dctx.keyNum; + + defaultKeyNum = dctx.keyNum; defaultAlgoId = dctx.keyType; memcpy(defaultKey, dctx.key, DESFIRE_MAX_KEY_SIZE); defaultKdfAlgo = dctx.kdfAlgo; defaultKdfInputLen = dctx.kdfInputLen; memcpy(defaultKdfInput, dctx.kdfInput, sizeof(dctx.kdfInput)); - defaultSecureChannel = securechann; - defaultCommSet = dctx.cmdSet; + defaultSecureChannel = securechann; + defaultCommSet = dctx.cmdSet; defaultCommMode = dctx.commMode; PrintAndLogEx(INFO, "-----------" _CYAN_("Default parameters") "---------------------------------"); @@ -5139,7 +5139,7 @@ static int CmdHF14ADesDefault(const char *Cmd) { PrintAndLogEx(INFO, "Secure chan : %s", CLIGetOptionListStr(DesfireSecureChannelOpts, defaultSecureChannel)); PrintAndLogEx(INFO, "Command set : %s", CLIGetOptionListStr(DesfireCommandSetOpts, defaultCommSet)); PrintAndLogEx(INFO, "Comm mode : %s", CLIGetOptionListStr(DesfireCommunicationModeOpts, defaultCommMode)); - + return PM3_SUCCESS; } @@ -5167,7 +5167,7 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - + DesfireContext dctx; int securechann = defaultSecureChannel; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); @@ -5175,27 +5175,27 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { CLIParserFree(ctx); return res; } - + SetAPDULogging(APDULogging); CLIParserFree(ctx); - + if (verbose) DesfirePrintContext(&dctx); - + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } - + res = DesfireAuthenticate(&dctx, securechann); //DACd40 DACEV1 if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - + if (DesfireIsAuthenticated(&dctx)) { if (verbose) PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); @@ -5205,20 +5205,20 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; - + res = DesfireGetAIDList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire GetAIDList command " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - + if (buflen >= 3) { PrintAndLogEx(INFO, "---- " _CYAN_("AID list") " ----"); for (int i = 0; i < buflen; i += 3) PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); } - + DropField(); return PM3_SUCCESS; } @@ -5247,7 +5247,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { bool APDULogging = arg_get_lit(ctx, 1); bool verbose = arg_get_lit(ctx, 2); - + DesfireContext dctx; int securechann = defaultSecureChannel; int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann); @@ -5255,27 +5255,27 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { CLIParserFree(ctx); return res; } - + SetAPDULogging(APDULogging); CLIParserFree(ctx); if (verbose) DesfirePrintContext(&dctx); - + res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire select " _RED_("error") "."); DropField(); return PM3_ESOFT; } - - res = DesfireAuthenticate(&dctx, securechann); + + res = DesfireAuthenticate(&dctx, securechann); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res); DropField(); return PM3_ESOFT; } - + if (DesfireIsAuthenticated(&dctx)) { if (verbose) PrintAndLogEx(ERR, "Desfire " _GREEN_("authenticated")); @@ -5285,7 +5285,7 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t buflen = 0; - + // result bytes: 3, 2, 1-16. total record size = 24 res = DesfireGetDFList(&dctx, buf, &buflen); if (res != PM3_SUCCESS) { @@ -5293,17 +5293,17 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { DropField(); return PM3_ESOFT; } - + if (buflen > 0) { PrintAndLogEx(INFO, "----------------------- " _CYAN_("File list") " -----------------------"); for (int i = 0; i < buflen; i++) - PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", - DesfireAIDByteToUint(&buf[i * 24 + 1]), - buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], - strlen((char *)&buf[i * 24 + 1 + 5]), - &buf[i * 24 + 1 + 5]); + PrintAndLogEx(INFO, "AID: %06x ISO file id: %02x%02x ISO DF name[%" PRIu32 "]: %s", + DesfireAIDByteToUint(&buf[i * 24 + 1]), + buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], + strlen((char *)&buf[i * 24 + 1 + 5]), + &buf[i * 24 + 1 + 5]); } - + DropField(); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 2414d83ef..935083ab4 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -31,7 +31,7 @@ #include #include #include "commonutil.h" -#include "crypto/libpcrypto.h" +#include "crypto/libpcrypto.h" #include "aes.h" #include "des.h" #include "ui.h" @@ -55,10 +55,14 @@ static inline void update_key_schedules(desfirekey_t key) { int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type) { switch (key_type) { - case T_DES: return 8; - case T_3DES: return 16; - case T_3K3DES: return 24; - case T_AES: return 16; + case T_DES: + return 8; + case T_3DES: + return 16; + case T_3K3DES: + return 24; + case T_AES: + return 16; } return 0; } diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 0d3baa5c3..71f3acb23 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -17,8 +17,8 @@ * * $Id$ */ - - #ifndef __DESFIRE_CRYPTO_H + +#ifndef __DESFIRE_CRYPTO_H #define __DESFIRE_CRYPTO_H #include "common.h" diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index ef8830302..9c4bb721b 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -207,7 +207,7 @@ void DesfireClearContext(DesfireContext *ctx) { ctx->keyNum = 0; ctx->keyType = T_DES; memset(ctx->key, 0, sizeof(ctx->key)); - + ctx->secureChannel = DACNone; ctx->cmdSet = DCCNative; ctx->commMode = DCMNone; @@ -226,41 +226,41 @@ void DesfireClearSession(DesfireContext *ctx) { memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC)); memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc)); memset(ctx->lastIV, 0, sizeof(ctx->lastIV)); - ctx->cntrTx = 0; + ctx->cntrTx = 0; ctx->cntrRx = 0; memset(ctx->TI, 0, sizeof(ctx->TI)); } void DesfirePrintContext(DesfireContext *ctx) { - PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", - ctx->keyNum, - CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), - desfire_get_key_length(ctx->keyType), - sprint_hex(ctx->key, - desfire_get_key_length(ctx->keyType))); - + PrintAndLogEx(INFO, "Key num: %d Key algo: %s Key[%d]: %s", + ctx->keyNum, + CLIGetOptionListStr(DesfireAlgoOpts, ctx->keyType), + desfire_get_key_length(ctx->keyType), + sprint_hex(ctx->key, + desfire_get_key_length(ctx->keyType))); + if (ctx->kdfAlgo != MFDES_KDF_ALGO_NONE) PrintAndLogEx(INFO, "KDF algo: %s KDF input[%d]: %s", CLIGetOptionListStr(DesfireKDFAlgoOpts, ctx->kdfAlgo), ctx->kdfInputLen, sprint_hex(ctx->kdfInput, ctx->kdfInputLen)); - - PrintAndLogEx(INFO, "Secure channel: %s Command set: %s Communication mode: %s", - CLIGetOptionListStr(DesfireSecureChannelOpts, ctx->secureChannel), - CLIGetOptionListStr(DesfireCommandSetOpts, ctx->cmdSet), - CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); - + + PrintAndLogEx(INFO, "Secure channel: %s Command set: %s Communication mode: %s", + CLIGetOptionListStr(DesfireSecureChannelOpts, ctx->secureChannel), + CLIGetOptionListStr(DesfireCommandSetOpts, ctx->cmdSet), + CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); + if (DesfireIsAuthenticated(ctx)) { - PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", - desfire_get_key_length(ctx->keyType), - sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType)), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType)), - desfire_get_key_block_length(ctx->keyType), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); - + PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", + desfire_get_key_length(ctx->keyType), + sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType)), + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType)), + desfire_get_key_block_length(ctx->keyType), + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); + } - } +} void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) { DesfireClearContext(ctx); - + ctx->keyNum = keyNum; ctx->keyType = keyType; memcpy(ctx->key, key, desfire_get_key_length(keyType)); @@ -322,11 +322,11 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin if (sw) *sw = isw; - if (isw != 0x9000 && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_SIGNATURE) && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_ADDITIONAL_FRAME) && - isw != DESFIRE_GET_ISO_STATUS(MFDES_S_NO_CHANGES)) { + if (isw != 0x9000 && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_SIGNATURE) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_ADDITIONAL_FRAME) && + isw != DESFIRE_GET_ISO_STATUS(MFDES_S_NO_CHANGES)) { if (GetAPDULogging()) { if (isw >> 8 == 0x61) { PrintAndLogEx(ERR, "APDU chaining len: 0x%02x -->", isw & 0xff); @@ -343,7 +343,7 @@ static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uin static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint8_t *respcode) { *result_len = 0; if (respcode) *respcode = 0xff; - + if (activate_field) { DropField(); msleep(50); @@ -369,21 +369,21 @@ static int DESFIRESendRaw(bool activate_field, uint8_t *data, size_t datalen, ui if (respcode) *respcode = rcode; memmove(&result[0], &result[1], *result_len); - if (rcode != MFDES_S_OPERATION_OK && - rcode != MFDES_S_SIGNATURE && - rcode != MFDES_S_ADDITIONAL_FRAME && - rcode != MFDES_S_NO_CHANGES) { + if (rcode != MFDES_S_OPERATION_OK && + rcode != MFDES_S_SIGNATURE && + rcode != MFDES_S_ADDITIONAL_FRAME && + rcode != MFDES_S_NO_CHANGES) { if (GetAPDULogging()) - PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode); + PrintAndLogEx(ERR, "Command (%02x) ERROR: 0x%02x", data[0], rcode); return PM3_EAPDU_FAIL; } return PM3_SUCCESS; } static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { - if (resplen) + if (resplen) *resplen = 0; - if (respcode) + if (respcode) *respcode = 0xff; uint8_t buf[255 * 5] = {0x00}; @@ -397,14 +397,14 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 cdata[0] = cmd; memcpy(&cdata[1], data, datalen); cdatalen = datalen + 1; - + int res = DESFIRESendRaw(activate_field, cdata, cdatalen, buf, sizeof(buf), &buflen, &rcode); if (res != PM3_SUCCESS) { uint16_t ssw = DESFIRE_GET_ISO_STATUS(rcode); PrintAndLogEx(DEBUG, "error DESFIRESendRaw %s", DesfireGetErrorString(res, &ssw)); return res; } - + if (resp) { if (splitbysize) { resp[0] = buflen; @@ -419,8 +419,8 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 pos += buflen; if (!enable_chaining) { if (rcode == MFDES_S_OPERATION_OK || - rcode == MFDES_ADDITIONAL_FRAME) { - if (resplen) + rcode == MFDES_ADDITIONAL_FRAME) { + if (resplen) *resplen = pos; } return PM3_SUCCESS; @@ -456,13 +456,13 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8 if (resplen) *resplen = (splitbysize) ? i : pos; - return PM3_SUCCESS; + return PM3_SUCCESS; } static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { - if (resplen) + if (resplen) *resplen = 0; - if (respcode) + if (respcode) *respcode = 0xff; uint16_t sw = 0; @@ -484,7 +484,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", DesfireGetErrorString(res, &sw)); return res; } - + if (respcode != NULL && ((sw & 0xff00) == 0x9100)) *respcode = sw & 0xff; @@ -500,8 +500,8 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t pos += buflen; if (!enable_chaining) { if (sw == DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) || - sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { - if (resplen) + sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) { + if (resplen) *resplen = pos; } return PM3_SUCCESS; @@ -541,23 +541,23 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t if (resplen) *resplen = (splitbysize) ? i : pos; - return PM3_SUCCESS; + return PM3_SUCCESS; } // move data from blockdata [format: ...] to single data block static void DesfireJoinBlockToBytes(uint8_t *blockdata, size_t blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t *dstdatalen) { *dstdatalen = 0; - for(int i = 0; i < blockdatacount; i++) { + for (int i = 0; i < blockdatacount; i++) { memcpy(&dstdata[*dstdatalen], &blockdata[i * blockdatasize + 1], blockdata[i * blockdatasize]); *dstdatalen += blockdata[i * blockdatasize]; } } -// move data from single data block to blockdata [format: ...] +// move data from single data block to blockdata [format: ...] // lengths in the blockdata is not changed. result - in the blockdata static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, size_t blockdatasize, uint8_t *dstdata, size_t dstdatalen) { size_t len = 0; - for(int i = 0; i < *blockdatacount; i++) { + for (int i = 0; i < *blockdatacount; i++) { size_t tlen = len + blockdata[i * blockdatasize]; if (tlen > dstdatalen) tlen = dstdatalen; @@ -572,20 +572,20 @@ static void DesfireSplitBytesToBlock(uint8_t *blockdata, size_t *blockdatacount, int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen, bool enable_chaining, size_t splitbysize) { int res = PM3_SUCCESS; - + uint8_t databuf[250 * 5] = {0}; size_t databuflen = 0; - - switch(ctx->cmdSet) { + + switch (ctx->cmdSet) { case DCCNative: case DCCNativeISO: DesfireSecureChannelEncode(ctx, cmd, data, datalen, databuf, &databuflen); - + if (ctx->cmdSet == DCCNative) res = DesfireExchangeNative(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); else res = DesfireExchangeISO(activate_field, ctx, cmd, databuf, databuflen, respcode, databuf, &databuflen, enable_chaining, splitbysize); - + if (splitbysize) { uint8_t sdata[250 * 5] = {0}; size_t sdatalen = 0; @@ -600,12 +600,12 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin } else { DesfireSecureChannelDecode(ctx, databuf, databuflen, *respcode, resp, resplen); } - break; + break; case DCCISO: return PM3_EAPDU_FAIL; - break; - } - + break; + } + return res; } @@ -616,24 +616,24 @@ int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t data int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) { if (aid1 == NULL) return PM3_EINVARG; - + uint8_t data[6] = {0}; memcpy(data, aid1, 3); - if (aid2 != NULL) + if (aid2 != NULL) memcpy(&data[3], aid2, 3); uint8_t resp[257] = {0}; size_t resplen = 0; uint8_t respcode = 0; - + int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, &respcode, resp, &resplen, true, 0); if (res == PM3_SUCCESS) { if (resplen != 0) return PM3_ECARDEXCHANGE; - + // select operation fail if (respcode != MFDES_S_OPERATION_OK) return PM3_EAPDU_FAIL; - + return PM3_SUCCESS; } return res; @@ -644,7 +644,7 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin DesfireAIDUintToByte(aid1, data); DesfireAIDUintToByte(aid2, &data[3]); - + return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } @@ -656,9 +656,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 different crypto arg1 DES, 3DES, 3K3DES, AES // 3 different communication modes, PLAIN,MAC,CRYPTO - + DesfireClearSession(dctx); - + if (secureChannel == DACNone) return PM3_SUCCESS; @@ -745,7 +745,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel // Part 2 uint32_t rndlen = recv_len; memcpy(encRndB, recv_data, rndlen); - + // Part 3 if (dctx->keyType == T_AES) { @@ -873,9 +873,9 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel Desfire_session_key_new(RndA, RndB, key, &sesskey); memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); -PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); -PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); - if (dctx->keyType == T_DES){ + PrintAndLogEx(INFO, "encRndA : %s", sprint_hex(encRndA, rndlen)); + PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); + if (dctx->keyType == T_DES) { if (secureChannel == DACd40) des_decrypt(encRndA, encRndA, key->data); if (secureChannel == DACEV1) @@ -892,8 +892,8 @@ PrintAndLogEx(INFO, "IV : %s", sprint_hex(IV, rndlen)); } rol(RndA, rndlen); -PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); -PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); + PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); + PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); for (uint32_t x = 0; x < rndlen; x++) { if (RndA[x] != encRndA[x]) { if (g_debugMode > 1) { @@ -916,10 +916,10 @@ PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); //key->cmac_sk1 and key->cmac_sk2 //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); } - + dctx->secureChannel = secureChannel; memcpy(dctx->sessionKeyMAC, dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType)); -PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); + PrintAndLogEx(INFO, "sessionKeyEnc : %s", sprint_hex(dctx->sessionKeyEnc, desfire_get_key_length(dctx->keyType))); return PM3_SUCCESS; } diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 873e365a8..f7d9b485c 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -49,12 +49,12 @@ typedef struct DesfireContextS { uint8_t keyNum; enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes uint8_t key[DESF_MAX_KEY_LEN]; - + // KDF finction uint8_t kdfAlgo; uint8_t kdfInputLen; uint8_t kdfInput[31]; - + DesfireSecureChannel secureChannel; // none/d40/ev1/ev2 DesfireCommandSet cmdSet; // native/nativeiso/iso DesfireCommunicationMode commMode; // plain/mac/enc @@ -81,7 +81,7 @@ void DesfireClearSession(DesfireContext *ctx); void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key); void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet); void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode); -void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo,uint8_t *kdfInput, uint8_t kdfInputLen); +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen); const char *DesfireGetErrorString(int res, uint16_t *sw); uint32_t DesfireAIDByteToUint(uint8_t *data); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 90aa643ce..49e3e6b05 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -25,20 +25,21 @@ void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { uint8_t data[1024] = {0}; - switch(ctx->keyType) { + switch (ctx->keyType) { case T_DES: if (ctx->secureChannel == DACd40) { if (encode) des_encrypt_ecb(data, srcdata, srcdatalen, ctx->key); else des_decrypt_ecb(data, srcdata, srcdatalen, ctx->key); - } if (ctx->secureChannel == DACEV1) { + } + if (ctx->secureChannel == DACEV1) { if (encode) des_encrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); else des_decrypt_cbc(data, srcdata, srcdatalen, ctx->key, ctx->IV); } - + if (dstdata) memcpy(dstdata, data, srcdatalen); break; @@ -60,11 +61,11 @@ void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatale static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - + uint8_t data[1024] = {0}; size_t rlen = 0; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMPlain: memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -72,7 +73,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint case DCMMACed: if (srcdatalen == 0) break; - + rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen); DesfireCryptoEncDec(ctx, data, rlen, NULL, true); @@ -87,7 +88,8 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint DesfireCryptoEncDec(ctx, data, rlen, dstdata, true); *dstdatalen = rlen; break; - case DCMNone:; + case DCMNone: + ; } } @@ -98,28 +100,29 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMPlain: case DCMMACed: data[0] = cmd; rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); memcpy(&data[1], srcdata, srcdatalen); DesfireCryptoEncDec(ctx, data, rlen, NULL, true); - + memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; - } + } break; case DCMEncrypted: break; - case DCMNone:; + case DCMNone: + ; } } void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { + switch (ctx->secureChannel) { case DACd40: DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); break; @@ -139,7 +142,7 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMMACed: break; @@ -150,19 +153,19 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; break; - } + } } static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - switch(ctx->commMode) { + switch (ctx->commMode) { case DCMPlain: case DCMMACed: memcpy(dstdata, srcdata, srcdatalen - 8); *dstdatalen = srcdatalen - 8; - + break; case DCMEncrypted: break; @@ -170,11 +173,11 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; break; - } + } } void DesfireSecureChannelDecode(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { - switch(ctx->secureChannel) { + switch (ctx->secureChannel) { case DACd40: DesfireSecureChannelDecodeD40(ctx, srcdata, srcdatalen, respcode, dstdata, dstdatalen); break; diff --git a/doc/commands.json b/doc/commands.json index c52b3bbf5..8f191e302 100644 --- a/doc/commands.json +++ b/doc/commands.json @@ -973,7 +973,7 @@ }, "help": { "command": "help", - "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210630.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", + "description": "help use ` help` for details of a command prefs { edit client/device preferences... } -------- ----------------------- technology ----------------------- analyse { analyse utils... } data { plot window / data buffer manipulation... } emv { emv iso-14443 / iso-7816... } hf { high frequency commands... } hw { hardware commands... } lf { low frequency commands... } nfc { nfc commands... } reveng { crc calculations from reveng software... } smart { smart card iso-7816 commands... } script { scripting commands... } trace { trace manipulation... } wiegand { wiegand format manipulation... } -------- ----------------------- general ----------------------- clear clear screen hints turn hints on / off msleep add a pause in milliseconds rem add a text line in log file quit exit exit program [=] session log e:\\proxspace\\pm3/.proxmark3/logs/log_20210706.txt --------------------------------------------------------------------------------------- auto available offline: no run lf search / hf search / data plot / data save", "notes": [ "auto" ], @@ -3938,6 +3938,31 @@ ], "usage": "hf mf wrbl [-hab] --blk [-k ] [-d ]" }, + "hf mfdes auth": { + "command": "hf mfdes auth", + "description": "authenticates mifare desfire using key", + "notes": [ + "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", + "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", + "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", + "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-m, --type auth type (1=normal, 2=iso, 3=aes)", + "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", + "-a, --aid aid used for authentification (hex 3 bytes)", + "-n, --keyno key number used for authentification", + "-k, --key key for checking (hex 8-24 bytes)", + "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", + "-i, --kdfi kdf input (hex 1-31 bytes)" + ], + "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" + }, "hf mfdes bruteaid": { "command": "hf mfdes bruteaid", "description": "recover aids by bruteforce. warning: this command takes a long time", @@ -4168,6 +4193,50 @@ ], "usage": "hf mfdes formatpicc [-h]" }, + "hf mfdes getaids": { + "command": "hf mfdes getaids", + "description": "get application ids list from card. master key needs to be provided.", + "notes": [ + "hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-a, --apdu show apdu requests and responses", + "-v, --verbose show technical data", + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" + ], + "usage": "hf mfdes getaids [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + }, + "hf mfdes getappnames": { + "command": "hf mfdes getappnames", + "description": "get application ids, iso ids and df names from card. master key needs to be provided.", + "notes": [ + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" + ], + "offline": false, + "options": [ + "-h, --help this help", + "-a, --apdu show apdu requests and responses", + "-v, --verbose show technical data", + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" + ], + "usage": "hf mfdes getappnames [-hav] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" + }, "hf mfdes getuid": { "command": "hf mfdes getuid", "description": "get uid from a mifare desfire tag", @@ -4196,28 +4265,23 @@ }, "hf mfdes help": { "command": "hf mfdes help", - "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes auth available offline: no authenticates mifare desfire using key", + "description": "help this help list list desfire (iso 14443a) history --------------------------------------------------------------------------------------- hf mfdes default available offline: no get application ids, iso ids and df names from card. master key needs to be provided.", "notes": [ - "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> aes,keynumber 0, aid 0x803201", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3des,keynumber 1, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> des,keynumber 2, aid 0x000000", - "hf mfdes auth -m 1 -t 1 -a 000000 -n 0 -> des, defaultkey, aid 0x000000", - "hf mfdes auth -m 2 -t 2 -a 000000 -n 0 -> 3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> 3k3des, defaultkey, aid 0x000000", - "hf mfdes auth -m 3 -t 4 -a 000000 -n 0 -> aes, defaultkey, aid 0x000000" + "hf mfdes getappnames -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup" ], "offline": true, "options": [ "-h, --help this help", - "-m, --type auth type (1=normal, 2=iso, 3=aes)", - "-t, --algo crypt algo (1=des, 2=3des(2k2des), 3=3k3des, 4=aes)", - "-a, --aid aid used for authentification (hex 3 bytes)", - "-n, --keyno key number used for authentification", - "-k, --key key for checking (hex 8-24 bytes)", - "-d, --kdf key derivation function (kdf) (0=none, 1=an10922, 2=gallagher)", - "-i, --kdfi kdf input (hex 1-31 bytes)" + "-n, --keyno key number", + "-t, --algo crypt algo: des, 2tdea, 3tdea, aes", + "-k, --key key for authenticate (hex 8(des), 16(2tdea or aes) or 24(3tdea) bytes)", + "-f, --kdf key derivation function (kdf): none, an10922, gallagher", + "-i, --kdfi kdf input (hex 1-31 bytes)", + "-m, --cmode communicaton mode: plain/mac/encrypt", + "-c, --ccset communicaton command set: native/niso/iso", + "-s, --schann secure channel: d40/ev1/ev2" ], - "usage": "hf mfdes auth [-h] [-m ] [-t ] [-a ]... [-n ] [-k ] [-d ] [-i ]" + "usage": "hf mfdes default [-h] [-n ] [-t ] [-k ] [-f ] [-i ] [-m ] [-c ] [-s ]" }, "hf mfdes info": { "command": "hf mfdes info", @@ -9217,8 +9281,8 @@ } }, "metadata": { - "commands_extracted": 572, + "commands_extracted": 575, "extracted_by": "PM3Help2JSON v1.00", - "extracted_on": "2021-06-30T09:30:39" + "extracted_on": "2021-07-06T09:14:57" } } \ No newline at end of file diff --git a/doc/commands.md b/doc/commands.md index a0625577c..c3b056e47 100644 --- a/doc/commands.md +++ b/doc/commands.md @@ -501,6 +501,7 @@ Check column "offline" for their availability. |command |offline |description |------- |------- |----------- |`hf mfdes help `|Y |`This help` +|`hf mfdes default `|N |`[new]Set defaults for all the commands` |`hf mfdes auth `|N |`Tries a MIFARE DesFire Authentication` |`hf mfdes changekey `|N |`Change Key` |`hf mfdes chk `|N |`Check keys` @@ -513,6 +514,8 @@ Check column "offline" for their availability. |`hf mfdes createaid `|N |`Create Application ID` |`hf mfdes deleteaid `|N |`Delete Application ID` |`hf mfdes selectaid `|N |`Select Application ID` +|`hf mfdes getaids `|N |`[new]Get Application IDs list` +|`hf mfdes getappnames `|N |`[new]Get Applications list` |`hf mfdes changevalue `|N |`Write value of a value file (credit/debit/clear)` |`hf mfdes clearfile `|N |`Clear record File` |`hf mfdes createfile `|N |`Create Standard/Backup File`