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}
};