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