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] 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);