From c22050b63835ff8584b83262fa5bfb826e0f8551 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 12:39:06 +0300 Subject: [PATCH 1/9] create new desfirecrypto --- client/CMakeLists.txt | 1 + client/Makefile | 1 + client/src/mifare/desfirecore.c | 55 ------------ client/src/mifare/desfirecore.h | 63 +------------ client/src/mifare/desfirecrypto.c | 123 ++++++++++++++++++++++++++ client/src/mifare/desfirecrypto.h | 91 +++++++++++++++++++ client/src/mifare/desfiresecurechan.c | 36 -------- client/src/mifare/desfiresecurechan.h | 3 +- 8 files changed, 220 insertions(+), 153 deletions(-) create mode 100644 client/src/mifare/desfirecrypto.c create mode 100644 client/src/mifare/desfirecrypto.h diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 4879e953b..536464d18 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/desfirecrypto.c ${PM3_ROOT}/client/src/mifare/desfiresecurechan.c ${PM3_ROOT}/client/src/mifare/desfirecore.c ${PM3_ROOT}/client/src/uart/uart_posix.c diff --git a/client/Makefile b/client/Makefile index 45ddffe31..7d09586a0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -589,6 +589,7 @@ SRCS = aiddesfire.c \ loclass/elite_crack.c \ loclass/ikeys.c \ mifare/desfire_crypto.c \ + mifare/desfirecrypto.c \ mifare/desfirecore.c \ mifare/desfiresecurechan.c \ mifare/mad.c \ diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 9c4bb721b..7fd1f2b28 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -203,34 +203,6 @@ void DesfireAIDUintToByte(uint32_t aid, uint8_t *data) { data[2] = (aid >> 16) & 0xff; } -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; - - ctx->kdfAlgo = 0; - ctx->kdfInputLen = 0; - memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput)); - - DesfireClearSession(ctx); -} - -void DesfireClearSession(DesfireContext *ctx) { - ctx->secureChannel = DACNone; // here none - not authenticared - - memset(ctx->IV, 0, sizeof(ctx->IV)); - 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->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, @@ -258,29 +230,6 @@ void DesfirePrintContext(DesfireContext *ctx) { } } -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)); -} - -void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet) { - ctx->cmdSet = cmdSet; -} - -void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode) { - ctx->commMode = commMode; -} - -void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen) { - ctx->kdfAlgo = kdfAlgo; - ctx->kdfInputLen = kdfInputLen; - if (kdfInputLen) - memcpy(ctx->kdfInput, kdfInput, kdfInputLen); -} - static int DESFIRESendApdu(bool activate_field, sAPDU apdu, uint8_t *result, uint32_t max_result_len, uint32_t *result_len, uint16_t *sw) { if (result_len) *result_len = 0; if (sw) *sw = 0; @@ -648,10 +597,6 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL); } -bool DesfireIsAuthenticated(DesfireContext *dctx) { - return dctx->secureChannel != DACNone; -} - 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 diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index f7d9b485c..e33cfa7aa 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -15,78 +15,22 @@ #include "common.h" #include "cliparser.h" +#include "mifare/desfirecrypto.h" #include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" -#define DESF_MAX_KEY_LEN 24 - -#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) - -typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; - -typedef enum { - DACNone, - DACd40, - DACEV1, - DACEV2 -} DesfireSecureChannel; - -typedef enum { - DCCNative, - DCCNativeISO, - DCCISO -} DesfireCommandSet; - -typedef enum { - DCMNone, - DCMPlain, - DCMMACed, - DCMEncrypted -} DesfireCommunicationMode; - - -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 - - uint8_t IV[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t - uint8_t lastIV[DESF_MAX_KEY_LEN]; - //mf4Session_t AESSession; - uint16_t cntrTx; // for AES - uint16_t cntrRx; // for AES - uint8_t TI[4]; // for AES -} DesfireContext; - extern const CLIParserOption DesfireAlgoOpts[]; extern const CLIParserOption DesfireKDFAlgoOpts[]; extern const CLIParserOption DesfireCommunicationModeOpts[]; extern const CLIParserOption DesfireCommandSetOpts[]; extern const CLIParserOption DesfireSecureChannelOpts[]; -void DesfireClearContext(DesfireContext *ctx); -void DesfirePrintContext(DesfireContext *ctx); -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); - const char *DesfireGetErrorString(int res, uint16_t *sw); uint32_t DesfireAIDByteToUint(uint8_t *data); void DesfireAIDUintToByte(uint32_t aid, uint8_t *data); +void DesfirePrintContext(DesfireContext *ctx); + int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *respcode, uint8_t *resp, size_t *resplen); 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); @@ -94,7 +38,6 @@ int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2); int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2); int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel); -bool DesfireIsAuthenticated(DesfireContext *dctx); int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c new file mode 100644 index 000000000..55c957932 --- /dev/null +++ b/client/src/mifare/desfirecrypto.c @@ -0,0 +1,123 @@ +/*- + * Copyright (C) 2010, Romain Tartiere. + * Copyright (C) 2021 Merlok + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + +#include "desfirecrypto.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 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; + + ctx->kdfAlgo = 0; + ctx->kdfInputLen = 0; + memset(ctx->kdfInput, 0, sizeof(ctx->kdfInput)); + + DesfireClearSession(ctx); +} + +void DesfireClearSession(DesfireContext *ctx) { + ctx->secureChannel = DACNone; // here none - not authenticared + + memset(ctx->IV, 0, sizeof(ctx->IV)); + 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->cntrRx = 0; + memset(ctx->TI, 0, sizeof(ctx->TI)); +} + +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)); +} + +void DesfireSetCommandSet(DesfireContext *ctx, DesfireCommandSet cmdSet) { + ctx->cmdSet = cmdSet; +} + +void DesfireSetCommMode(DesfireContext *ctx, DesfireCommunicationMode commMode) { + ctx->commMode = commMode; +} + +void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint8_t kdfInputLen) { + ctx->kdfAlgo = kdfAlgo; + ctx->kdfInputLen = kdfInputLen; + if (kdfInputLen) + memcpy(ctx->kdfInput, kdfInput, kdfInputLen); +} + +bool DesfireIsAuthenticated(DesfireContext *dctx) { + return dctx->secureChannel != DACNone; +} + +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; + } +} + diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h new file mode 100644 index 000000000..9fc3d61e0 --- /dev/null +++ b/client/src/mifare/desfirecrypto.h @@ -0,0 +1,91 @@ +/*- + * Copyright (C) 2010, Romain Tartiere. + * Copyright (C) 2021 Merlok + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see + * + * $Id$ + */ + +#ifndef __DESFIRECRYPTO_H +#define __DESFIRECRYPTO_H + +#include "common.h" +#include "mifare/desfire_crypto.h" +#include "mifare/mifare4.h" + +#define DESF_MAX_KEY_LEN 24 + +#define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) + +typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; + +typedef enum { + DACNone, + DACd40, + DACEV1, + DACEV2 +} DesfireSecureChannel; + +typedef enum { + DCCNative, + DCCNativeISO, + DCCISO +} DesfireCommandSet; + +typedef enum { + DCMNone, + DCMPlain, + DCMMACed, + DCMEncrypted +} DesfireCommunicationMode; + + +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 + + uint8_t IV[DESF_MAX_KEY_LEN]; + uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; + uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t + uint8_t lastIV[DESF_MAX_KEY_LEN]; + //mf4Session_t AESSession; + uint16_t cntrTx; // for AES + uint16_t cntrRx; // for AES + uint8_t TI[4]; // for AES +} DesfireContext; + +void DesfireClearContext(DesfireContext *ctx); +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); +bool DesfireIsAuthenticated(DesfireContext *dctx); + + +void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); + + +#endif // __DESFIRECRYPTO_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 49e3e6b05..f7e7d22ea 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -22,42 +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}; - - 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; diff --git a/client/src/mifare/desfiresecurechan.h b/client/src/mifare/desfiresecurechan.h index df997eb54..23810c791 100644 --- a/client/src/mifare/desfiresecurechan.h +++ b/client/src/mifare/desfiresecurechan.h @@ -15,11 +15,10 @@ #include "common.h" #include "mifare/desfirecore.h" +#include "mifare/desfirecrypto.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); From 5f0f6b8032be89df04e1dbf277c9993d6f320fcc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:22:01 +0300 Subject: [PATCH 2/9] update crypto encode/decode --- client/src/mifare/desfire_crypto.h | 10 +- client/src/mifare/desfirecrypto.c | 163 ++++++++++++++++++++++---- client/src/mifare/desfirecrypto.h | 27 +++-- client/src/mifare/desfiresecurechan.c | 6 +- 4 files changed, 161 insertions(+), 45 deletions(-) diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index 71f3acb23..346a7e50c 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -25,10 +25,9 @@ #include "mifare.h" // structs #include "crc32.h" #include "crypto/libpcrypto.h" +#include "mifare/desfirecrypto.h" -#define MAX_CRYPTO_BLOCK_SIZE 16 -#define DESFIRE_MAX_KEY_SIZE 24 /* Mifare DESFire EV1 Application crypto operations */ #define APPLICATION_CRYPTO_DES 0x00 #define APPLICATION_CRYPTO_3K3DES 0x40 @@ -75,13 +74,6 @@ typedef enum { /* Error code managed by the library */ #define CRYPTO_ERROR 0x01 -enum DESFIRE_CRYPTOALGO { - T_DES = 0x00, - T_3DES = 0x01, //aka 2K3DES - T_3K3DES = 0x02, - T_AES = 0x03 -}; - int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type); size_t desfire_get_key_block_length(enum DESFIRE_CRYPTOALGO key_type); diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 55c957932..e0a886b62 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -24,6 +24,8 @@ #include #include #include "ui.h" +#include "aes.h" +#include "des.h" #include "crc.h" #include "crc16.h" // crc16 ccitt #include "crc32.h" @@ -85,39 +87,152 @@ bool DesfireIsAuthenticated(DesfireContext *dctx) { return dctx->secureChannel != DACNone; } -void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { - uint8_t data[1024] = {0}; +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}; + memcpy(sdata, data, block_size); + if (dir_to_send) { + bin_xor(sdata, ivect, block_size); + } - switch (ctx->keyType) { + uint8_t edata[MAX_CRYPTO_BLOCK_SIZE] = {0}; + + switch (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); + if (encode) + des_encrypt(edata, sdata, key); + else + des_decrypt(edata, sdata, key); break; case T_3DES: + if (encode) { + mbedtls_des3_context ctx3; + mbedtls_des3_set2key_enc(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } else { + mbedtls_des3_context ctx3; + mbedtls_des3_set2key_dec(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } break; case T_3K3DES: + if (encode) { + mbedtls_des3_context ctx3; + mbedtls_des3_set3key_enc(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } else { + mbedtls_des3_context ctx3; + mbedtls_des3_set3key_dec(&ctx3, key); + mbedtls_des3_crypt_ecb(&ctx3, sdata, edata); + } 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); + if (encode) { + mbedtls_aes_context actx; + mbedtls_aes_init(&actx); + mbedtls_aes_setkey_enc(&actx, key, 128); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_ENCRYPT, sdata, edata); + mbedtls_aes_free(&actx); + } else { + mbedtls_aes_context actx; + mbedtls_aes_init(&actx); + mbedtls_aes_setkey_dec(&actx, key, 128); + mbedtls_aes_crypt_ecb(&actx, MBEDTLS_AES_DECRYPT, sdata, edata); + mbedtls_aes_free(&actx); + } break; } + + memcpy(dstdata, edata, block_size); + + if (dir_to_send) { + memcpy(ivect, sdata, block_size); + } else { + memcpy(ivect, data, block_size); + } +} + +void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode) { + uint8_t data[1024] = {0}; + + if (ctx->secureChannel == DACd40) + memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); + + size_t block_size = desfire_get_key_block_length(ctx->keyType); + size_t offset = 0; + while (offset < srcdatalen) { + //mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); + if (use_session_key) + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + else + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + offset += block_size; + } + + if (dstdata) + memcpy(dstdata, data, srcdatalen); +} + +static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) { + int kbs = desfire_get_key_block_length(ctx->keyType); + const uint8_t R = (kbs == 8) ? 0x1B : 0x87; + + uint8_t l[kbs]; + memset(l, 0, kbs); + + uint8_t ivect[kbs]; + memset(ivect, 0, kbs); + + //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); + DesfireCryptoEncDec(ctx, true, l, kbs, NULL, true); + + bool txor = false; + + // Used to compute CMAC on complete blocks + memcpy(sk1, l, kbs); + txor = l[0] & 0x80; + lsl(sk1, kbs); + if (txor) { + sk1[kbs - 1] ^= R; + } + + // Used to compute CMAC on the last block if non-complete + memcpy(sk2, sk1, kbs); + txor = sk1[0] & 0x80; + lsl(sk2, kbs); + if (txor) { + sk2[kbs - 1] ^= R; + } +} + +void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t *cmac) { + int kbs = desfire_get_key_block_length(ctx->keyType); + if (kbs == 0) + return; + + uint8_t buffer[kbs]; + memset(buffer, 0, kbs); + + uint8_t sk1[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + uint8_t sk2[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCMACGenerateSubkeys(ctx, sk1, sk2); + + memcpy(buffer, data, len); + + if ((!len) || (len % kbs)) { + buffer[len++] = 0x80; + while (len % kbs) { + buffer[len++] = 0x00; + } + bin_xor(buffer + len - kbs, sk2, kbs); + } else { + bin_xor(buffer + len - kbs, sk1, kbs); + } + + //mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); + DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); + + memcpy(cmac, ctx->IV, kbs); + } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 9fc3d61e0..236601406 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -22,13 +22,21 @@ #define __DESFIRECRYPTO_H #include "common.h" -#include "mifare/desfire_crypto.h" #include "mifare/mifare4.h" -#define DESF_MAX_KEY_LEN 24 +#define MAX_CRYPTO_BLOCK_SIZE 16 +#define DESFIRE_MAX_CRYPTO_BLOCK_SIZE 16 +#define DESFIRE_MAX_KEY_SIZE 24 #define DESFIRE_GET_ISO_STATUS(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) +enum DESFIRE_CRYPTOALGO { + T_DES = 0x00, + T_3DES = 0x01, //aka 2K3DES + T_3K3DES = 0x02, + T_AES = 0x03 +}; + typedef enum DESFIRE_CRYPTOALGO DesfireCryptoAlgorythm; typedef enum { @@ -54,8 +62,8 @@ typedef enum { typedef struct DesfireContextS { uint8_t keyNum; - enum DESFIRE_CRYPTOALGO keyType; // des/2tdea/3tdea/aes - uint8_t key[DESF_MAX_KEY_LEN]; + DesfireCryptoAlgorythm keyType; // des/2tdea/3tdea/aes + uint8_t key[DESFIRE_MAX_KEY_SIZE]; // KDF finction uint8_t kdfAlgo; @@ -66,10 +74,10 @@ typedef struct DesfireContextS { DesfireCommandSet cmdSet; // native/nativeiso/iso DesfireCommunicationMode commMode; // plain/mac/enc - uint8_t IV[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN]; - uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t - uint8_t lastIV[DESF_MAX_KEY_LEN]; + uint8_t IV[DESFIRE_MAX_KEY_SIZE]; + 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]; //mf4Session_t AESSession; uint16_t cntrTx; // for AES uint16_t cntrRx; // for AES @@ -85,7 +93,8 @@ void DesfireSetKdf(DesfireContext *ctx, uint8_t kdfAlgo, uint8_t *kdfInput, uint bool DesfireIsAuthenticated(DesfireContext *dctx); -void DesfireCryptoEncDec(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); +void DesfireCryptoEncDec(DesfireContext *ctx, bool use_session_key, uint8_t *srcdata, size_t srcdatalen, uint8_t *dstdata, bool encode); +void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); #endif // __DESFIRECRYPTO_H diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index f7e7d22ea..51f2af365 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -40,7 +40,7 @@ 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); - DesfireCryptoEncDec(ctx, data, rlen, NULL, true); + DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); memcpy(&dstdata[srcdatalen], ctx->IV, 4); *dstdatalen = rlen; @@ -49,7 +49,7 @@ static void DesfireSecureChannelEncodeD40(DesfireContext *ctx, uint8_t cmd, uint 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); + DesfireCryptoEncDec(ctx, true, data, rlen, dstdata, true); *dstdatalen = rlen; break; case DCMNone: @@ -70,7 +70,7 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint 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); + DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { From fffef000eac4aa733d77a4ef04e4ad35a212c20d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 16:46:05 +0300 Subject: [PATCH 3/9] mac des/ev1 calculated --- client/src/mifare/desfirecrypto.c | 5 ++++- client/src/mifare/desfiresecurechan.c | 21 +++++++++++++++++++-- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index e0a886b62..98a095b0c 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -184,7 +184,8 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ memset(ivect, 0, kbs); //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); - DesfireCryptoEncDec(ctx, true, l, kbs, NULL, true); + DesfireCryptoEncDec(ctx, true, l, kbs, l, true); +//PrintAndLogEx(INFO, "i: %s", sprint_hex(l, kbs)); bool txor = false; @@ -218,6 +219,8 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * DesfireCMACGenerateSubkeys(ctx, sk1, sk2); memcpy(buffer, data, len); +PrintAndLogEx(INFO, "sk1: %s", sprint_hex(sk1, 8)); +PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); if ((!len) || (len % kbs)) { buffer[len++] = 0x80; diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index 51f2af365..c1924c2fd 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -70,11 +70,13 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint data[0] = cmd; rlen = padded_data_length(srcdatalen + 1, desfire_get_key_block_length(ctx->keyType)); memcpy(&data[1], srcdata, srcdatalen); - DesfireCryptoEncDec(ctx, true, data, rlen, NULL, true); + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, rlen, cmac); +PrintAndLogEx(INFO, "MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { - memcpy(&dstdata[srcdatalen], ctx->IV, 4); + memcpy(&dstdata[srcdatalen], cmac, 8); *dstdatalen = rlen; } break; @@ -121,6 +123,9 @@ 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}; + size_t rlen = 0; + memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -129,6 +134,18 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, case DCMMACed: memcpy(dstdata, srcdata, srcdatalen - 8); *dstdatalen = srcdatalen - 8; + + memcpy(data, srcdata, *dstdatalen); + data[*dstdatalen] = respcode; + rlen = padded_data_length(*dstdatalen + 1, desfire_get_key_block_length(ctx->keyType)); + + uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; + DesfireCryptoCMAC(ctx, data, rlen, cmac); +PrintAndLogEx(INFO, "MACp: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); +PrintAndLogEx(INFO, "MACc: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + if (memcmp(&srcdata[*dstdatalen], cmac, desfire_get_key_block_length(ctx->keyType)) != 0) { + PrintAndLogEx(WARNING, "Received MAC is not match with calculated"); + } break; case DCMEncrypted: From ae53e38335145ae75d6518e8f681656df52568b6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 6 Jul 2021 18:41:52 +0300 Subject: [PATCH 4/9] add application create/delete commands --- client/src/mifare/desfirecore.c | 28 ++++++++++++++++++++++++++++ client/src/mifare/desfirecore.h | 2 ++ 2 files changed, 30 insertions(+) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 7fd1f2b28..96d5f66cd 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -862,6 +862,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel //memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType)); } + memset(dctx->IV, 0, DESFIRE_MAX_KEY_SIZE); 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))); @@ -888,3 +889,30 @@ int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen) { return PM3_EAPDU_FAIL; return PM3_SUCCESS; } + +int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen) { + uint8_t respcode = 0xff; + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchangeEx(false, dctx, MFDES_CREATE_APPLICATION, appdata, appdatalen, &respcode, resp, &resplen, true, 24); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + +int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid) { + uint8_t respcode = 0xff; + uint8_t data[3] = {0}; + DesfireAIDUintToByte(aid, data); + uint8_t resp[257] = {0}; + size_t resplen = 0; + int res = DesfireExchangeEx(false, dctx, MFDES_DELETE_APPLICATION, data, sizeof(data), &respcode, resp, &resplen, true, 24); + if (res != PM3_SUCCESS) + return res; + if (respcode != MFDES_S_OPERATION_OK || resplen != 0) + return PM3_EAPDU_FAIL; + return PM3_SUCCESS; +} + diff --git a/client/src/mifare/desfirecore.h b/client/src/mifare/desfirecore.h index e33cfa7aa..9eaa74f9a 100644 --- a/client/src/mifare/desfirecore.h +++ b/client/src/mifare/desfirecore.h @@ -42,5 +42,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); int DesfireGetDFList(DesfireContext *dctx, uint8_t *resp, size_t *resplen); +int DesfireCreateApplication(DesfireContext *dctx, uint8_t *appdata, size_t appdatalen); +int DesfireDeleteApplication(DesfireContext *dctx, uint32_t aid); #endif // __DESFIRECORE_H From 857ce0ea1714546a4d1c412a3013d834c98396e4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:16:45 +0300 Subject: [PATCH 5/9] fix multiple sprint_hex --- client/src/mifare/desfirecore.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/client/src/mifare/desfirecore.c b/client/src/mifare/desfirecore.c index 96d5f66cd..862723587 100644 --- a/client/src/mifare/desfirecore.c +++ b/client/src/mifare/desfirecore.c @@ -220,12 +220,14 @@ void DesfirePrintContext(DesfireContext *ctx) { CLIGetOptionListStr(DesfireCommunicationModeOpts, ctx->commMode)); if (DesfireIsAuthenticated(ctx)) { - PrintAndLogEx(INFO, "Session key MAC [%d]: %s ENC: %s IV [%d]: %s", + PrintAndLogEx(INFO, "Session key MAC [%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)), + sprint_hex(ctx->sessionKeyMAC, desfire_get_key_length(ctx->keyType))); + PrintAndLogEx(INFO, " ENC: %s", + sprint_hex(ctx->sessionKeyEnc, desfire_get_key_length(ctx->keyType))); + PrintAndLogEx(INFO, " IV [%d]: %s", desfire_get_key_block_length(ctx->keyType), - sprint_hex(ctx->sessionKeyEnc, desfire_get_key_block_length(ctx->keyType))); + sprint_hex(ctx->IV, desfire_get_key_block_length(ctx->keyType))); } } From 0f0ef4435ed05d5cc4dc5e6cbdf829578adc3b71 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:17:35 +0300 Subject: [PATCH 6/9] add mac length and fix encode/decode --- client/src/mifare/desfirecrypto.c | 58 ++++++++++++++++++++++++++----- client/src/mifare/desfirecrypto.h | 2 ++ 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 98a095b0c..6982cff6f 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -26,6 +26,7 @@ #include "ui.h" #include "aes.h" #include "des.h" +#include #include "crc.h" #include "crc16.h" // crc16 ccitt #include "crc32.h" @@ -87,6 +88,25 @@ bool DesfireIsAuthenticated(DesfireContext *dctx) { return dctx->secureChannel != DACNone; } +size_t DesfireGetMACLength(DesfireContext *ctx) { + size_t mac_length = MAC_LENGTH; + switch (ctx->secureChannel) { + case DACNone: + mac_length = 0; + break; + case DACd40: + mac_length = 4; + break; + case DACEV1: + mac_length = 8; + break; + case DACEV2: + mac_length = 8; + break; + } + return mac_length; +} + 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}; @@ -146,33 +166,49 @@ static void DesfireCryptoEncDecSingleBlock(uint8_t *key, DesfireCryptoAlgorythm memcpy(dstdata, edata, block_size); if (dir_to_send) { - memcpy(ivect, sdata, block_size); + memcpy(ivect, edata, block_size); } else { memcpy(ivect, data, block_size); } } -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) { uint8_t data[1024] = {0}; + uint8_t xiv[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; if (ctx->secureChannel == DACd40) memset(ctx->IV, 0, DESFIRE_MAX_CRYPTO_BLOCK_SIZE); - + size_t block_size = desfire_get_key_block_length(ctx->keyType); + + if (iv == NULL) + memcpy(xiv, ctx->IV, block_size); + else + memcpy(xiv, iv, block_size); + size_t offset = 0; while (offset < srcdatalen) { //mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); if (use_session_key) - DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, xiv, encode, encode); else - DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, ctx->IV, encode, encode); + DesfireCryptoEncDecSingleBlock(ctx->key, ctx->keyType, srcdata + offset, data, xiv, encode, encode); offset += block_size; } + if (iv == NULL) + memcpy(ctx->IV, xiv, block_size); + else + memcpy(iv, xiv, block_size); + if (dstdata) memcpy(dstdata, data, srcdatalen); } +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); +} + static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_t *sk2) { int kbs = desfire_get_key_block_length(ctx->keyType); const uint8_t R = (kbs == 8) ? 0x1B : 0x87; @@ -184,7 +220,7 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ memset(ivect, 0, kbs); //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); - DesfireCryptoEncDec(ctx, true, l, kbs, l, true); + DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, ivect); //PrintAndLogEx(INFO, "i: %s", sprint_hex(l, kbs)); bool txor = false; @@ -211,14 +247,15 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * if (kbs == 0) return; - uint8_t buffer[kbs]; - memset(buffer, 0, kbs); + uint8_t buffer[padded_data_length(len, kbs)]; + memset(buffer, 0, sizeof(buffer)); uint8_t sk1[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; uint8_t sk2[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; DesfireCMACGenerateSubkeys(ctx, sk1, sk2); memcpy(buffer, data, len); +PrintAndLogEx(INFO, "key: %s", sprint_hex(ctx->sessionKeyMAC, 24)); PrintAndLogEx(INFO, "sk1: %s", sprint_hex(sk1, 8)); PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); @@ -227,15 +264,18 @@ PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); while (len % kbs) { buffer[len++] = 0x00; } +PrintAndLogEx(INFO, "befode xor sk1: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk2, kbs); } else { +PrintAndLogEx(INFO, "befode xor sk2: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk1, kbs); } +PrintAndLogEx(INFO, "cbuf: %s", sprint_hex(buffer, len)); +PrintAndLogEx(INFO, "iv: %s", sprint_hex(ctx->IV, kbs)); //mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); memcpy(cmac, ctx->IV, kbs); - } diff --git a/client/src/mifare/desfirecrypto.h b/client/src/mifare/desfirecrypto.h index 236601406..b9f28f31a 100644 --- a/client/src/mifare/desfirecrypto.h +++ b/client/src/mifare/desfirecrypto.h @@ -91,9 +91,11 @@ 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); bool DesfireIsAuthenticated(DesfireContext *dctx); +size_t DesfireGetMACLength(DesfireContext *ctx); 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 DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *srcdata, size_t srcdatalen, uint8_t *cmac); From 81028914916671cf107b1134f9dbfea4414d71db Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:18:12 +0300 Subject: [PATCH 7/9] ev1/mac and ev1/plain works --- client/src/mifare/desfiresecurechan.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/client/src/mifare/desfiresecurechan.c b/client/src/mifare/desfiresecurechan.c index c1924c2fd..b437ebc07 100644 --- a/client/src/mifare/desfiresecurechan.c +++ b/client/src/mifare/desfiresecurechan.c @@ -59,7 +59,6 @@ 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; @@ -68,16 +67,14 @@ static void DesfireSecureChannelEncodeEV1(DesfireContext *ctx, uint8_t cmd, uint 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); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, rlen, cmac); -PrintAndLogEx(INFO, "MAC: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); + DesfireCryptoCMAC(ctx, data, srcdatalen + 1, cmac); memcpy(dstdata, srcdata, srcdatalen); if (srcdatalen != 0 && ctx->commMode == DCMMACed) { - memcpy(&dstdata[srcdatalen], cmac, 8); - *dstdatalen = rlen; + memcpy(&dstdata[srcdatalen], cmac, DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen + DesfireGetMACLength(ctx); } break; case DCMEncrypted: @@ -124,7 +121,6 @@ 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}; - size_t rlen = 0; memcpy(dstdata, srcdata, srcdatalen); *dstdatalen = srcdatalen; @@ -132,19 +128,21 @@ static void DesfireSecureChannelDecodeEV1(DesfireContext *ctx, uint8_t *srcdata, switch (ctx->commMode) { case DCMPlain: case DCMMACed: - memcpy(dstdata, srcdata, srcdatalen - 8); - *dstdatalen = srcdatalen - 8; + if (srcdatalen < DesfireGetMACLength(ctx)) + break; + + memcpy(dstdata, srcdata, srcdatalen - DesfireGetMACLength(ctx)); + *dstdatalen = srcdatalen - DesfireGetMACLength(ctx); memcpy(data, srcdata, *dstdatalen); data[*dstdatalen] = respcode; - rlen = padded_data_length(*dstdatalen + 1, desfire_get_key_block_length(ctx->keyType)); uint8_t cmac[DESFIRE_MAX_CRYPTO_BLOCK_SIZE] = {0}; - DesfireCryptoCMAC(ctx, data, rlen, cmac); -PrintAndLogEx(INFO, "MACp: %s", sprint_hex(&srcdata[*dstdatalen], desfire_get_key_block_length(ctx->keyType))); -PrintAndLogEx(INFO, "MACc: %s", sprint_hex(cmac, desfire_get_key_block_length(ctx->keyType))); - if (memcmp(&srcdata[*dstdatalen], cmac, desfire_get_key_block_length(ctx->keyType)) != 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; From d963ec833242632a97ecfbada1285dec1ecf6c7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:25:26 +0300 Subject: [PATCH 8/9] remove debug --- client/src/mifare/desfirecrypto.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/client/src/mifare/desfirecrypto.c b/client/src/mifare/desfirecrypto.c index 6982cff6f..187744ec7 100644 --- a/client/src/mifare/desfirecrypto.c +++ b/client/src/mifare/desfirecrypto.c @@ -188,7 +188,6 @@ void DesfireCryptoEncDecEx(DesfireContext *ctx, bool use_session_key, uint8_t *s size_t offset = 0; while (offset < srcdatalen) { - //mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); if (use_session_key) DesfireCryptoEncDecSingleBlock(ctx->sessionKeyMAC, ctx->keyType, srcdata + offset, data, xiv, encode, encode); else @@ -219,9 +218,7 @@ static void DesfireCMACGenerateSubkeys(DesfireContext *ctx, uint8_t *sk1, uint8_ uint8_t ivect[kbs]; memset(ivect, 0, kbs); - //mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_SEND, MCO_ENCYPHER); DesfireCryptoEncDecEx(ctx, true, l, kbs, l, true, ivect); -//PrintAndLogEx(INFO, "i: %s", sprint_hex(l, kbs)); bool txor = false; @@ -255,25 +252,17 @@ void DesfireCryptoCMAC(DesfireContext *ctx, uint8_t *data, size_t len, uint8_t * DesfireCMACGenerateSubkeys(ctx, sk1, sk2); memcpy(buffer, data, len); -PrintAndLogEx(INFO, "key: %s", sprint_hex(ctx->sessionKeyMAC, 24)); -PrintAndLogEx(INFO, "sk1: %s", sprint_hex(sk1, 8)); -PrintAndLogEx(INFO, "sk2: %s", sprint_hex(sk2, 8)); if ((!len) || (len % kbs)) { buffer[len++] = 0x80; while (len % kbs) { buffer[len++] = 0x00; } -PrintAndLogEx(INFO, "befode xor sk1: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk2, kbs); } else { -PrintAndLogEx(INFO, "befode xor sk2: %s", sprint_hex(buffer, len)); bin_xor(buffer + len - kbs, sk1, kbs); } -PrintAndLogEx(INFO, "cbuf: %s", sprint_hex(buffer, len)); -PrintAndLogEx(INFO, "iv: %s", sprint_hex(ctx->IV, kbs)); - //mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); DesfireCryptoEncDec(ctx, true, buffer, len, NULL, true); memcpy(cmac, ctx->IV, kbs); From 6e207be3acae5800544fef0d997ebd9be5bea668 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Jul 2021 16:31:23 +0300 Subject: [PATCH 9/9] added `there is no applications` message if it there is no app) --- client/src/cmdhfmfdes.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 4204b8a3c..7526207e3 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -5217,6 +5217,8 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) { PrintAndLogEx(INFO, "---- " _CYAN_("AID list") " ----"); for (int i = 0; i < buflen; i += 3) PrintAndLogEx(INFO, "AID: %06x", DesfireAIDByteToUint(&buf[i])); + } else { + PrintAndLogEx(INFO, "There is no applications on the card"); } DropField(); @@ -5302,12 +5304,15 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) { buf[i * 24 + 1 + 3], buf[i * 24 + 1 + 4], strlen((char *)&buf[i * 24 + 1 + 5]), &buf[i * 24 + 1 + 5]); + } else { + PrintAndLogEx(INFO, "There is no applications on the card"); } DropField(); return PM3_SUCCESS; } + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help"}, {"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"}, @@ -5340,6 +5345,8 @@ static command_t CommandTable[] = { {"getvalue", CmdHF14ADesGetValueData, IfPm3Iso14443a, "Get value of file"}, {"read", CmdHF14ADesReadData, IfPm3Iso14443a, "Read data from standard/backup/record file"}, {"write", CmdHF14ADesWriteData, IfPm3Iso14443a, "Write data to standard/backup/record file"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("System") " -----------------------"}, +// {"test", CmdHF14ADesTest, IfPm3Iso14443a, "Test crypto"}, {NULL, NULL, NULL, NULL} };