diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 77c7ad595..cf15dd0d9 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -6334,7 +6334,7 @@ static int CmdHF14ADesReadData(const char *Cmd) { FileSettingsS fsettings; DesfireCommunicationMode commMode = dctx.commMode; - DesfireSetCommMode(&dctx, DCMMACed); + DesfireSetCommMode(&dctx, DCMPlain); res = DesfireGetFileSettingsStruct(&dctx, fnum, &fsettings); DesfireSetCommMode(&dctx, commMode); @@ -6365,6 +6365,9 @@ static int CmdHF14ADesReadData(const char *Cmd) { } DesfireSetCommMode(&dctx, fsettings.commMode); + + if (fsettings.fileCommMode != 0 && noauth) + PrintAndLogEx(WARNING, "File needs communication mode `%s` but there is no authentication", CLIGetOptionListStr(DesfireCommunicationModeOpts, fsettings.commMode)); if (verbose) PrintAndLogEx(INFO, "Got file type: %s. Option: %s. comm mode: %s", diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index b6bb5e961..be98106a7 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -212,14 +212,12 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm 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) { +void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, bool encode, uint8_t *iv) { uint8_t data[1024] = {0}; uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - bool xencode = encode; if (ctx->secureChannel == DACd40) { memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); - xencode = false; } size_t block_size = desfire_get_key_block_length(ctx->keyType); @@ -232,9 +230,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 + offset, xiv, encode, xencode); + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); else - DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, encode, xencode); + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data + offset, xiv, dir_to_send, encode); offset += block_size; } @@ -248,7 +246,12 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s } void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { - DesfireCryptoEncDecEx(ctx, use_session_key, srcdata, srcdatalen, dstdata, encode, NULL); + bool dir_to_send = encode; + bool xencode = encode; + if (ctx->secureChannel == DACd40) + xencode = false; + + DesfireCryptoEncDecEx(ctx, use_session_key, srcdata, srcdatalen, dstdata, dir_to_send, xencode, NULL); } static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) { @@ -261,7 +264,7 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ uint8_t ivect[kbs]; memset(ivect, 0, kbs); - DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, ivect); + DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, true, ivect); bool txor = false; diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index a559f11a9..fddef64c9 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -99,7 +99,7 @@ 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); +void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool dir_to_send, bool encode, uint8_t *iv); void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); void DesfireDESKeySetVersion(uint8_t *key, DesfireCryptoAlgorythm keytype, uint8_t version); diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 13a3b907e..fb51f9d92 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -58,6 +58,7 @@ static const AllowedChannelModesS AllowedChannelModes[] = { {MFDES_DEBIT, DACd40, DCCNative, DCMPlain}, {MFDES_COMMIT_TRANSACTION, DACd40, DCCNative, DCMPlain}, {MFDES_CLEAR_RECORD_FILE, DACd40, DCCNative, DCMPlain}, + {MFDES_GET_FILE_SETTINGS, DACd40, DCCNative, DCMPlain}, {MFDES_GET_VALUE, DACd40, DCCNative, DCMMACed}, {MFDES_CREDIT, DACd40, DCCNative, DCMMACed}, @@ -249,16 +250,31 @@ void DesfireSecureChannelEncode(DesfireContext *ctx, uint8_t cmd, uint8_t *srcda } static void DesfireSecureChannelDecodeD40(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t respcode, 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 DCMMACed: - //if (srcdatalen > 4) - // *dstdatalen = srcdatalen - 4; - // TODO check MAC!!! - + case DCMMACed: { + size_t maclen = DesfireGetMACLength(ctx); + if (srcdatalen > maclen) { + uint8_t mac[16] = {0}; + rlen = padded_data_length(srcdatalen - maclen, desfire_get_key_block_length(ctx->keyType)); + memcpy(data, srcdata, srcdatalen - maclen); + DesfireCryptoEncDecEx(ctx, true, data, rlen, NULL, true, true, mac); + + if (memcmp(mac, &srcdata[srcdatalen - maclen], maclen) == 0) { + *dstdatalen = srcdatalen - maclen; + } else { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + //PrintAndLogEx(INFO, " received MAC: %s", sprint_hex(&srcdata[srcdatalen - maclen], maclen)); + //PrintAndLogEx(INFO, " calculated MAC: %s", sprint_hex(mac, maclen)); + } + } break; + } case DCMEncrypted: if (srcdatalen < desfire_get_key_block_length(ctx->keyType)) { memcpy(dstdata, srcdata, srcdatalen);