From c99002c5e07c384945579872039d84e76e9e7183 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 17:59:42 +0300 Subject: [PATCH 01/14] add Get UID command --- client/src/mifare/desfirecore.c | 10 ++++++++++ client/src/mifare/desfirecore.h | 1 + 2 files changed, 11 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 862723587..ad4c6c545 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -872,6 +872,16 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel return PM3_SUCCESS; } +int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { + uint8_t respcode = 0xff; + int res = DesfireExchange(dctx, MFDES_GET_UID, NULL, 0, &respcode, resp, resplen); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { uint8_t respcode = 0xff; int res = DesfireExchange(dctx, MFDES_GET_APPLICATION_IDS, NULL, 0, &respcode, resp, resplen); diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index 9eaa74f9a..080fed18d 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -39,6 +39,7 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); +int DesfireGetUID(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); From ca983f1473f10f233b4cf8adbd1466ac804f08e9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:06:38 +0300 Subject: [PATCH 02/14] cmac can be NULL --- client/src/mifare/desfirecrypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 187744ec7..8960b8b96 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -265,6 +265,7 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); - memcpy(cmac, ctx->IV, kbs); + if (cmac != NULL) + memcpy(cmac, ctx->IV, kbs); } From ebcb86570e4b213e66075631ff58e4ab157f6eeb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 18:41:20 +0300 Subject: [PATCH 03/14] fix length bug in the encode/decode --- client/src/mifare/desfirecrypto.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 8960b8b96..f6e316096 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -189,9 +189,9 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s size_t offset = 0; while (offset < srcdatalen) { if (use_session_key) - DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, xiv, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data + offset, xiv, encode, encode); else - DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, xiv, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, encode, encode); offset += block_size; } From 567cbadc58ef76b2805c1cc085d2254a6cac99ee Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Jul 2021 17:04:44 +0300 Subject: [PATCH 04/14] add some session params --- client/src/mifare/desfirecrypto.c | 2 ++ client/src/mifare/desfirecrypto.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index f6e316096..9beeefe7b 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -56,6 +56,8 @@ 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->lastCommand = 0; + ctx->lastRequestZeroLen = false; ctx->cntrTx = 0; ctx->cntrRx = 0; memset(ctx->TI, 0, sizeof(ctx->TI)); diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index b9f28f31a..4c0eb0a2f 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -78,6 +78,8 @@ typedef struct DesfireContextS { uint8_t sessionKeyMAC[DESFIRE_MAX_KEY_SIZE]; uint8_t sessionKeyEnc[DESFIRE_MAX_KEY_SIZE]; // look at mifare4.h - mf4Session_t uint8_t lastIV[DESFIRE_MAX_KEY_SIZE]; + uint8_t lastCommand; + bool lastRequestZeroLen; //mf4Session_t AESSession; uint16_t cntrTx; // for AES uint16_t cntrRx; // for AES From 8fd896478e9e23261eee73f8f9fc735c72b11eb9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Jul 2021 17:07:02 +0300 Subject: [PATCH 05/14] ev1 channel reorganized --- client/src/mifare/desfiresecurechan.c | 101 ++++++++++++++------------ 1 file changed, 53 insertions(+), 48 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index b437ebc07..58b7dd4f1 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -60,31 +60,34 @@ 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}; - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; + // we calc MAC anyway + // if encypted channel and no data - we only calc MAC + if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && srcdatalen == 0)) { + data[0] = cmd; + memcpy(&data[1], srcdata, srcdatalen); + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); +PrintAndLogEx(INFO, "mac iv: %s", sprint_hex(ctx->IV, 16)); - switch (ctx->commMode) { - case DCMPlain: - case DCMMACed: - data[0] = cmd; - memcpy(&data[1], srcdata, srcdatalen); - uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); - - memcpy(dstdata, srcdata, srcdatalen); - if (srcdatalen != 0 && ctx->commMode == DCMMACed) { - memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); - *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); - } - break; - case DCMEncrypted: - break; - case DCMNone: - ; + memcpy(dstdata, srcdata, srcdatalen); + if (srcdatalen != 0 && ctx->commMode == DCMMACed) { + memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); + } + } else if (ctx->commMode == DCMEncrypted) { + + + + } else { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; } } void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, size_t *dstdatalen) { + ctx->lastCommand = cmd; + ctx->lastRequestZeroLen = (srcdatalen == 0); + switch (ctx->secureChannel) { case DACd40: DesfireSecureChannelEncodeD40(ctx, cmd, srcdata, srcdatalen, dstdata, dstdatalen); @@ -122,36 +125,38 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, uint8_t *dstdata, size_t *dstdatalen) { uint8_t data[1024] = {0}; - memcpy(dstdata, srcdata, srcdatalen); - *dstdatalen = srcdatalen; - - switch (ctx->commMode) { - case DCMPlain: - case DCMMACed: - if (srcdatalen < DesfireGetMACLength(ctx)) - break; - - memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); - *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); - - memcpy(data, srcdata, *dstdatalen); - data[*dstdatalen] = respcode; - - uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); - if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { - PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); - PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); - PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); - } - - break; - case DCMEncrypted: - break; - case DACNone: + // if comm mode = plain --> response with MAC + // if request is not zero length --> response MAC + if (ctx->commMode == DCMPlain || ctx->commMode == DCMMACed || (ctx->commMode == DCMEncrypted && !ctx->lastRequestZeroLen)) { + if (srcdatalen < DesfireGetMACLength(ctx)) { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; - break; + return; + } + + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); + + memcpy(data, srcdata, *dstdatalen); + data[*dstdatalen] = respcode; + + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, *dstdatalen + 1, cmac); + if (memcmp(&srcdata[*dstdatalen], cmac, DesfireGetMACLength(ctx)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); + PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + } + } else if (ctx->commMode == DCMEncrypted) { + //mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); +PrintAndLogEx(INFO, "data: %s", sprint_hex(srcdata, srcdatalen)); +PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); +PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); + PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + } else { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; } } From cf7949c1f8e48556cced08d4cf73062469444d9e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Jul 2021 18:26:07 +0300 Subject: [PATCH 06/14] fix chaining --- client/src/mifare/desfirecrypto.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 5cd045713..b65512b23 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -165,13 +165,14 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm break; } - memcpy(dstdata, edata, block_size); - if (dir_to_send) { memcpy(ivect, edata, block_size); } else { + bin_xor(edata, ivect, block_size); memcpy(ivect, data, block_size); } + + memcpy(dstdata, edata, block_size); } void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv) { From 0fa708acb2eb5222855e77cf401e282b2b9b6af3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 01:26:47 +0300 Subject: [PATCH 07/14] add crc32 check --- client/src/mifare/desfire_crypto.c | 6 ++++++ client/src/mifare/desfire_crypto.h | 1 + 2 files changed, 7 insertions(+) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 935083ab4..137eb8089 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -976,6 +976,12 @@ void desfire_crc32_append(uint8_t *data, const size_t len) { crc32_ex(data, len, data + len); } +bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc) { + uint8_t ccrc[4] = {0}; + crc32_ex(data, len, ccrc); + return (memcmp(ccrc, crc, 4) == 0); +} + void iso14443a_crc_append(uint8_t *data, size_t len) { return compute_crc(CRC_14443_A, data, len, data + len, data + len + 1); } diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 346a7e50c..8cdf76ab6 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -149,6 +149,7 @@ void mifare_kdf_an10922(const desfirekey_t key, const uint8_t *data, size_t len) void desfire_crc32(const uint8_t *data, const size_t len, uint8_t *crc); void desfire_crc32_append(uint8_t *data, const size_t len); +bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); void iso14443a_crc_append(uint8_t *data, size_t len); void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc); #endif From 2fde5d90aea63047a6e74e137100762dbf8ad910 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 01:27:28 +0300 Subject: [PATCH 08/14] crc32 ok, ev1/enc channel ok. --- client/src/mifare/desfiresecurechan.c | 49 ++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 58b7dd4f1..c854ce861 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -67,7 +67,6 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint memcpy(&data[1], srcdata, srcdatalen); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); -PrintAndLogEx(INFO, "mac iv: %s", sprint_hex(ctx->IV, 16)); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { @@ -148,12 +147,52 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); } } else if (ctx->commMode == DCMEncrypted) { - //mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); -PrintAndLogEx(INFO, "data: %s", sprint_hex(srcdata, srcdatalen)); -PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); + if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); -PrintAndLogEx(INFO, "dec iv: %s", sprint_hex(ctx->IV, 16)); PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + + size_t crcpos = srcdatalen - 1; + while (crcpos > 0) + if (dstdata[crcpos] == 0) + crcpos--; + else + break; + crcpos++; // crc may be 0x00000000 + *dstdatalen = crcpos; + PrintAndLogEx(INFO, "crcpos: %d", crcpos); + if (crcpos < 4) { + PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); + return; + } + + uint8_t crcdata[1024] = {0}; + bool crcok = false; + for (int i = 0; i < 5; i++) { + if (crcpos == 0) + break; + if (crcpos - i + 4 > srcdatalen) + continue; + + memcpy(crcdata, dstdata, crcpos - i); + crcdata[crcpos - i] = respcode; + if (desfire_crc32_check(crcdata, crcpos - i + 1, &dstdata[crcpos - i])) { + crcpos -= i; + crcok = true; + break; + } + } + + if (crcok) { + *dstdatalen = crcpos; + } else { + PrintAndLogEx(WARNING, "CRC32 error. pos: %d", crcpos); + } + } else { memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; From 70bedbd7d10b7ac7aba0eba4fdaa34ce7ae705d5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 01:41:25 +0300 Subject: [PATCH 09/14] fix some d40 channel conditions --- client/src/mifare/desfiresecurechan.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c854ce861..5f9fec5a9 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -40,15 +40,20 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint rlen = padded_data_length(srcdatalen, desfire_get_key_block_length(ctx->keyType)); memcpy(data, srcdata, srcdatalen); + memset(ctx->IV, 0, sizeof(ctx->IV)); DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; break; case DCMEncrypted: + if (srcdatalen == 0) + break; + 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]); + memset(ctx->IV, 0, sizeof(ctx->IV)); DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); *dstdatalen = rlen; break; From ec79e35dcc916c53568286cf6df272c9dd5500ac Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 13:08:49 +0300 Subject: [PATCH 10/14] add crc16 check --- client/src/mifare/desfire_crypto.c | 8 +++++++- client/src/mifare/desfire_crypto.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/client/src/mifare/desfire_crypto.c b/client/src/mifare/desfire_crypto.c index 137eb8089..23c8b1fd9 100644 --- a/client/src/mifare/desfire_crypto.c +++ b/client/src/mifare/desfire_crypto.c @@ -978,7 +978,7 @@ void desfire_crc32_append(uint8_t *data, const size_t len) { bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc) { uint8_t ccrc[4] = {0}; - crc32_ex(data, len, ccrc); + desfire_crc32(data, len, ccrc); return (memcmp(ccrc, crc, 4) == 0); } @@ -989,3 +989,9 @@ void iso14443a_crc_append(uint8_t *data, size_t len) { void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc) { return compute_crc(CRC_14443_A, data, len, pbtCrc, pbtCrc + 1); } + +bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc) { + uint8_t ccrc[2] = {0}; + iso14443a_crc(data, len, ccrc); + return (memcmp(ccrc, crc, 2) == 0); +} diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 8cdf76ab6..689c0d56c 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -152,4 +152,5 @@ void desfire_crc32_append(uint8_t *data, const size_t len); bool desfire_crc32_check(uint8_t *data, const size_t len, uint8_t *crc); void iso14443a_crc_append(uint8_t *data, size_t len); void iso14443a_crc(uint8_t *data, size_t len, uint8_t *pbtCrc); +bool iso14443a_crc_check(uint8_t *data, const size_t len, uint8_t *crc); #endif From a7f39a1b79f3800960de69db948ebb0b83ed4134 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 13:09:59 +0300 Subject: [PATCH 11/14] move crc search function to desfirecrypto --- client/src/mifare/desfirecrypto.c | 44 +++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 1 + client/src/mifare/desfiresecurechan.c | 39 +++--------------------- 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index b65512b23..246545e9e 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -109,6 +109,50 @@ size_t DesfireGetMACLength(DesfireContext *ctx) { return mac_length; } +size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint8_t crclen) { + size_t crcpos = datalen - 1; + while (crcpos > 0) + if (data[crcpos] == 0) + crcpos--; + else + break; + crcpos++; // crc may be 0x00000000 or 0x0000 + PrintAndLogEx(INFO, "crcpos: %d", crcpos); + if (crcpos < crclen) { + PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); + return 0; + } + + uint8_t crcdata[1024] = {0}; + bool crcok = false; + for (int i = 0; i < crclen + 1; i++) { + PrintAndLogEx(INFO, "--crcpos: %d", crcpos - i); + if (crcpos - i == 0) + break; + if (crcpos - i + crclen > datalen) + continue; + PrintAndLogEx(INFO, "--crcposcheck: %d", crcpos - i); + + memcpy(crcdata, data, crcpos - i); + crcdata[crcpos - i] = respcode; + bool res; + if (crclen == 4) + res = desfire_crc32_check(crcdata, crcpos - i + 1, &data[crcpos - i]); + else + res = iso14443a_crc_check(crcdata, crcpos - i + 1, &data[crcpos - i]); + if (res) { + PrintAndLogEx(INFO, "--crc OK pos: %d", crcpos - i); + crcpos -= i; + crcok = true; + break; + } + } + if (!crcok) + crcpos = 0; + + return crcpos; +} + static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) { size_t block_size = desfire_get_key_block_length(keyType); uint8_t sdata[MAX_CRYPTO_BLOCK_SIZE] = {0}; diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index ff12335e6..824225b39 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -95,6 +95,7 @@ void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint bool DesfireIsAuthenticated(DesfireContext *dctx); size_t DesfireGetMACLength(DesfireContext *ctx); +size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint8_t crclen); void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode, uint8_t *iv); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 5f9fec5a9..b62a0a056 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -161,41 +161,12 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); - size_t crcpos = srcdatalen - 1; - while (crcpos > 0) - if (dstdata[crcpos] == 0) - crcpos--; - else - break; - crcpos++; // crc may be 0x00000000 - *dstdatalen = crcpos; - PrintAndLogEx(INFO, "crcpos: %d", crcpos); - if (crcpos < 4) { - PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); - return; - } - - uint8_t crcdata[1024] = {0}; - bool crcok = false; - for (int i = 0; i < 5; i++) { - if (crcpos == 0) - break; - if (crcpos - i + 4 > srcdatalen) - continue; - - memcpy(crcdata, dstdata, crcpos - i); - crcdata[crcpos - i] = respcode; - if (desfire_crc32_check(crcdata, crcpos - i + 1, &dstdata[crcpos - i])) { - crcpos -= i; - crcok = true; - break; - } - } - - if (crcok) { - *dstdatalen = crcpos; + size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); + if (puredatalen != 0) { + *dstdatalen = puredatalen; } else { - PrintAndLogEx(WARNING, "CRC32 error. pos: %d", crcpos); + PrintAndLogEx(WARNING, "CRC32 error."); + *dstdatalen = srcdatalen; } } else { From bed25108f6c52b3895794b77b5356a75ad1ccf41 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 13:14:42 +0300 Subject: [PATCH 12/14] d40/enc works --- client/src/mifare/desfiresecurechan.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index b62a0a056..dd66b9e54 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -117,6 +117,22 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, break; case DCMEncrypted: + if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { + memcpy(dstdata, srcdata, srcdatalen); + *dstdatalen = srcdatalen; + return; + } + + DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); + PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + + size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2); + if (puredatalen != 0) { + *dstdatalen = puredatalen; + } else { + PrintAndLogEx(WARNING, "CRC32 error."); + *dstdatalen = srcdatalen; + } break; case DCMPlain: case DACNone: From 77a66a024b108cfa9bcb8e4db9f95169a43c9ee0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 14:01:22 +0300 Subject: [PATCH 13/14] remove debug --- client/src/mifare/desfiresecurechan.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index dd66b9e54..c2001bdf0 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -124,13 +124,13 @@ static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, } DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); - PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 2); if (puredatalen != 0) { *dstdatalen = puredatalen; } else { - PrintAndLogEx(WARNING, "CRC32 error."); + PrintAndLogEx(WARNING, "CRC16 error."); *dstdatalen = srcdatalen; } break; @@ -175,7 +175,7 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, } DesfireCryptoEncDec(ctx, true, srcdata, srcdatalen, dstdata, false); - PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); + //PrintAndLogEx(INFO, "decoded[%d]: %s", srcdatalen, sprint_hex(dstdata, srcdatalen)); size_t puredatalen = DesfireSearchCRCPos(dstdata, srcdatalen, respcode, 4); if (puredatalen != 0) { From 08d8ac4f9f42096752d70cc7a2ecbb73a80b1680 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 9 Jul 2021 14:01:57 +0300 Subject: [PATCH 14/14] fix bug with false-positive crc16 and remove debug --- client/src/mifare/desfirecrypto.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 246545e9e..87fb4e1a1 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -117,21 +117,18 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint else break; crcpos++; // crc may be 0x00000000 or 0x0000 - PrintAndLogEx(INFO, "crcpos: %d", crcpos); if (crcpos < crclen) { PrintAndLogEx(WARNING, "No space for crc. pos: %d", crcpos); return 0; } uint8_t crcdata[1024] = {0}; - bool crcok = false; + size_t crcposfound = 0; for (int i = 0; i < crclen + 1; i++) { - PrintAndLogEx(INFO, "--crcpos: %d", crcpos - i); if (crcpos - i == 0) break; if (crcpos - i + crclen > datalen) continue; - PrintAndLogEx(INFO, "--crcposcheck: %d", crcpos - i); memcpy(crcdata, data, crcpos - i); crcdata[crcpos - i] = respcode; @@ -139,18 +136,13 @@ size_t DesfireSearchCRCPos(uint8_t *data, size_t datalen, uint8_t respcode, uint if (crclen == 4) res = desfire_crc32_check(crcdata, crcpos - i + 1, &data[crcpos - i]); else - res = iso14443a_crc_check(crcdata, crcpos - i + 1, &data[crcpos - i]); + res = iso14443a_crc_check(data, crcpos - i, &data[crcpos - i]); if (res) { - PrintAndLogEx(INFO, "--crc OK pos: %d", crcpos - i); - crcpos -= i; - crcok = true; - break; + crcposfound = crcpos - i; } } - if (!crcok) - crcpos = 0; - return crcpos; + return crcposfound; } static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm keyType, uint8_t *data, uint8_t *dstdata, uint8_t *ivect, bool dir_to_send, bool encode) {