mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-02-19 00:36:05 +08:00
regactoring desfire commands. textual fixes
This commit is contained in:
parent
0d00f56777
commit
1b2442ec36
6 changed files with 223 additions and 181 deletions
|
|
@ -1,5 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2014 Iceman
|
||||
// Copyright (C) 2021 Merlok
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
|
|
@ -4997,6 +4998,133 @@ static int CmdHF14aDesMAD(const char *Cmd) {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
*/
|
||||
static uint8_t defaultKeyNum = 0;
|
||||
static enum DESFIRE_CRYPTOALGO defaultAlgoId = T_DES;
|
||||
static uint8_t defaultKey[DESFIRE_MAX_KEY_SIZE] = {0};
|
||||
static int defaultKdfAlgo = MFDES_KDF_ALGO_NONE;
|
||||
static int defaultKdfInputLen = 0;
|
||||
static uint8_t defaultKdfInput[50] = {0};
|
||||
static DesfireSecureChannel defaultSecureChannel = DACEV1;
|
||||
static DesfireCommandSet defaultCommSet = DCCNativeISO;
|
||||
static DesfireCommunicationMode defaultCommMode = DCMPlain;
|
||||
|
||||
static int CmdDesGetSessionParameters(CLIParserContext *ctx, DesfireContext *dctx,
|
||||
uint8_t keynoid, uint8_t algoid, uint8_t keyid,
|
||||
uint8_t kdfid, uint8_t kdfiid,
|
||||
uint8_t cmodeid, uint8_t ccsetid, uint8_t schannid,
|
||||
int *securechannel) {
|
||||
|
||||
uint8_t keynum = defaultKeyNum;
|
||||
int algores = defaultAlgoId;
|
||||
uint8_t key[DESFIRE_MAX_KEY_SIZE] = {0};
|
||||
memcpy(key, defaultKey, DESFIRE_MAX_KEY_SIZE);
|
||||
int kdfAlgo = defaultKdfAlgo;
|
||||
int kdfInputLen = defaultKdfInputLen;
|
||||
uint8_t kdfInput[50] = {0};
|
||||
memcpy(kdfInput, defaultKdfInput, defaultKdfInputLen);
|
||||
int commmode = defaultCommMode;
|
||||
int commset = defaultCommSet;
|
||||
int secchann = defaultSecureChannel;
|
||||
|
||||
if (keynoid) {
|
||||
keynum = arg_get_int_def(ctx, keynoid, keynum);
|
||||
}
|
||||
|
||||
const CLIParserOption algo_opts[] = {
|
||||
{T_DES, "des"},
|
||||
{T_3DES, "2tdea"},
|
||||
{T_3K3DES, "3tdea"},
|
||||
{T_AES, "aes"},
|
||||
};
|
||||
|
||||
if (algoid) {
|
||||
if (CLIGetOptionList(arg_get_str(ctx, algoid), algo_opts, ARRAY_LENGTH(algo_opts), &algores))
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores));
|
||||
}
|
||||
|
||||
if (keyid) {
|
||||
int keylen = 0;
|
||||
uint8_t keydata[200] = {0};
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, keyid), keydata, sizeof(keydata), &keylen))
|
||||
return PM3_ESOFT;
|
||||
if (keylen && keylen != key_size(algores)) {
|
||||
PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores), key_size(algores), keylen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (keylen)
|
||||
memcpy(key, keydata, keylen);
|
||||
}
|
||||
|
||||
if (kdfid) {
|
||||
const CLIParserOption kdf_opts[] = {
|
||||
{MFDES_KDF_ALGO_NONE, "none"},
|
||||
{MFDES_KDF_ALGO_AN10922, "an10922"},
|
||||
{MFDES_KDF_ALGO_GALLAGHER, "gallagher"},
|
||||
};
|
||||
|
||||
if (CLIGetOptionList(arg_get_str(ctx, kdfid), kdf_opts, ARRAY_LENGTH(kdf_opts), &kdfAlgo))
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kdfAlgo));
|
||||
|
||||
}
|
||||
|
||||
if (kdfiid) {
|
||||
int datalen = kdfInputLen;
|
||||
uint8_t data[200] = {0};
|
||||
if (CLIParamHexToBuf(arg_get_str(ctx, kdfiid), data, sizeof(data), &datalen))
|
||||
return PM3_ESOFT;
|
||||
if (datalen) {
|
||||
kdfInputLen = datalen;
|
||||
memcpy(kdfInput, data, datalen);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmodeid) {
|
||||
const CLIParserOption cmode_opts[] = {
|
||||
{DCMPlain, "plain"},
|
||||
{DCMMACed, "mac"},
|
||||
{DCMEncrypted, "encrypt"},
|
||||
};
|
||||
|
||||
if (CLIGetOptionList(arg_get_str(ctx, cmodeid), cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode))
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode));
|
||||
}
|
||||
|
||||
if (ccsetid) {
|
||||
const CLIParserOption commc_opts[] = {
|
||||
{DCCNative, "native"},
|
||||
{DCCNativeISO, "niso"},
|
||||
{DCCISO, "iso"},
|
||||
};
|
||||
|
||||
if (CLIGetOptionList(arg_get_str(ctx, ccsetid), commc_opts, ARRAY_LENGTH(commc_opts), &commset))
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commset));
|
||||
}
|
||||
|
||||
if (schannid) {
|
||||
const CLIParserOption authc_opts[] = {
|
||||
{DACd40, "d40"},
|
||||
{DACEV1, "ev1"},
|
||||
{DACEV2, "ev2"},
|
||||
};
|
||||
|
||||
if (CLIGetOptionList(arg_get_str(ctx, schannid), authc_opts, ARRAY_LENGTH(authc_opts), &secchann))
|
||||
return PM3_ESOFT;
|
||||
PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), secchann));
|
||||
}
|
||||
|
||||
DesfireSetKey(dctx, keynum, algores, key);
|
||||
DesfireSetKdf(dctx, kdfAlgo, kdfInput, kdfInputLen);
|
||||
DesfireSetCommandSet(dctx, commset);
|
||||
DesfireSetCommMode(dctx, commmode);
|
||||
if (securechannel)
|
||||
*securechannel = secchann;
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
|
|
@ -5013,102 +5141,38 @@ static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
|||
arg_str0("k", "key", "<Key>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
|
||||
arg_str0("f", "kdf", "<none/AN10922/gallagher>", "Key Derivation Function (KDF): None, AN10922, Gallagher"),
|
||||
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Commpunicaton mode: plain/mac/encrypt"),
|
||||
arg_str0("c", "commc", "<native/niso/iso>", "Commpunicaton channel: native/niso/iso"),
|
||||
arg_str0("u", "authc", "<d40/ev1/ev2>", "Authentication channel: d40/ev1/ev2"),
|
||||
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool APDULogging = arg_get_lit(ctx, 1);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId
|
||||
|
||||
|
||||
const CLIParserOption algo_opts[] = {
|
||||
{T_DES, "des"},
|
||||
{T_3DES, "2tdea"},
|
||||
{T_3K3DES, "3tdea"},
|
||||
{T_AES, "aes"},
|
||||
};
|
||||
|
||||
int ares = T_DES;
|
||||
CLIGetOptionListWithReturn(ctx, 4, algo_opts, ARRAY_LENGTH(algo_opts), &ares);
|
||||
PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares));
|
||||
|
||||
int keylen = 0;
|
||||
uint8_t key[200] = {0};
|
||||
CLIGetHexWithReturn(ctx, 5, key, &keylen);
|
||||
if (keylen == 0) {
|
||||
keylen = key_size(ares);
|
||||
//memcpy(key, defaultkey, key_size(ares));
|
||||
}
|
||||
if (keylen != key_size(ares)) {
|
||||
PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares), key_size(ares), keylen);
|
||||
DesfireContext dctx;
|
||||
int securechann = defaultSecureChannel;
|
||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann);
|
||||
if (res) {
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
return res;
|
||||
}
|
||||
|
||||
const CLIParserOption kdf_opts[] = {
|
||||
{MFDES_KDF_ALGO_NONE, "none"},
|
||||
{MFDES_KDF_ALGO_AN10922, "an10922"},
|
||||
{MFDES_KDF_ALGO_GALLAGHER, "gallagher"},
|
||||
};
|
||||
|
||||
int kres = MFDES_KDF_ALGO_NONE;
|
||||
CLIGetOptionListWithReturn(ctx, 6, kdf_opts, ARRAY_LENGTH(kdf_opts), &kres);
|
||||
PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kres));
|
||||
|
||||
int kdfInputLen = 0;
|
||||
uint8_t kdfInput[50] = {0};
|
||||
CLIGetHexWithReturn(ctx, 7, kdfInput, &kdfInputLen);
|
||||
|
||||
const CLIParserOption cmode_opts[] = {
|
||||
{DCMPlain, "plain"},
|
||||
{DCMMACed, "mac"},
|
||||
{DCMEncrypted, "encrypt"},
|
||||
};
|
||||
|
||||
int commmode = DCMPlain;
|
||||
CLIGetOptionListWithReturn(ctx, 8, cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode);
|
||||
PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode));
|
||||
|
||||
const CLIParserOption commc_opts[] = {
|
||||
{DCCNative, "native"},
|
||||
{DCCNativeISO, "niso"},
|
||||
{DCCISO, "iso"},
|
||||
};
|
||||
|
||||
int commchann = DCCNativeISO;
|
||||
CLIGetOptionListWithReturn(ctx, 9, commc_opts, ARRAY_LENGTH(commc_opts), &commchann);
|
||||
PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann));
|
||||
|
||||
const CLIParserOption authc_opts[] = {
|
||||
{DACd40, "d40"},
|
||||
{DACEV1, "ev1"},
|
||||
{DACEV2, "ev2"},
|
||||
};
|
||||
|
||||
int authchann = DACEV1;
|
||||
CLIGetOptionListWithReturn(ctx, 10, authc_opts, ARRAY_LENGTH(authc_opts), &authchann);
|
||||
PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann));
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
DesfireContext dctx;
|
||||
DesfireSetKey(&dctx, keyNum, ares, key); // T_DES T_3DES T_3K3DES T_AES
|
||||
DesfireSetCommandChannel(&dctx, commchann);
|
||||
if (verbose)
|
||||
DesfirePrintContext(&dctx);
|
||||
|
||||
|
||||
int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
|
||||
res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Desfire select " _RED_("error") ".");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
res = DesfireAuthenticate(&dctx, authchann); //DACd40 DACEV1
|
||||
res = DesfireAuthenticate(&dctx, securechann); //DACd40 DACEV1
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res);
|
||||
DropField();
|
||||
|
|
@ -5157,102 +5221,38 @@ static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
|||
arg_str0("k", "key", "<Key>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
|
||||
arg_str0("f", "kdf", "<none/AN10922/gallagher>", "Key Derivation Function (KDF): None, AN10922, Gallagher"),
|
||||
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Commpunicaton mode: plain/mac/encrypt"),
|
||||
arg_str0("c", "commc", "<native/niso/iso>", "Commpunicaton channel: native/niso/iso"),
|
||||
arg_str0("u", "authc", "<d40/ev1/ev2>", "Authentication channel: d40/ev1/ev2"),
|
||||
arg_str0("m", "cmode", "<plain/mac/encrypt>", "Communicaton mode: plain/mac/encrypt"),
|
||||
arg_str0("c", "ccset", "<native/niso/iso>", "Communicaton command set: native/niso/iso"),
|
||||
arg_str0("s", "schann", "<d40/ev1/ev2>", "Secure channel: d40/ev1/ev2"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
bool APDULogging = arg_get_lit(ctx, 1);
|
||||
bool verbose = arg_get_lit(ctx, 2);
|
||||
uint8_t keyNum = arg_get_int_def(ctx, 3, 0); // defaultKeyId
|
||||
|
||||
|
||||
const CLIParserOption algo_opts[] = {
|
||||
{T_DES, "des"},
|
||||
{T_3DES, "2tdea"},
|
||||
{T_3K3DES, "3tdea"},
|
||||
{T_AES, "aes"},
|
||||
};
|
||||
|
||||
int ares = T_DES;
|
||||
CLIGetOptionListWithReturn(ctx, 4, algo_opts, ARRAY_LENGTH(algo_opts), &ares);
|
||||
PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares));
|
||||
|
||||
int keylen = 0;
|
||||
uint8_t key[200] = {0};
|
||||
CLIGetHexWithReturn(ctx, 5, key, &keylen);
|
||||
if (keylen == 0) {
|
||||
keylen = key_size(ares);
|
||||
//memcpy(key, defaultkey, key_size(ares));
|
||||
}
|
||||
if (keylen != key_size(ares)) {
|
||||
PrintAndLogEx(ERR, "%s key must have %d bytes length instead of %d.", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), ares), key_size(ares), keylen);
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
const CLIParserOption kdf_opts[] = {
|
||||
{MFDES_KDF_ALGO_NONE, "none"},
|
||||
{MFDES_KDF_ALGO_AN10922, "an10922"},
|
||||
{MFDES_KDF_ALGO_GALLAGHER, "gallagher"},
|
||||
};
|
||||
|
||||
int kres = MFDES_KDF_ALGO_NONE;
|
||||
CLIGetOptionListWithReturn(ctx, 6, kdf_opts, ARRAY_LENGTH(kdf_opts), &kres);
|
||||
PrintAndLogEx(INFO, "kdf funct: %s", CLIGetOptionListStr(kdf_opts, ARRAY_LENGTH(kdf_opts), kres));
|
||||
|
||||
int kdfInputLen = 0;
|
||||
uint8_t kdfInput[50] = {0};
|
||||
CLIGetHexWithReturn(ctx, 7, kdfInput, &kdfInputLen);
|
||||
|
||||
const CLIParserOption cmode_opts[] = {
|
||||
{DCMPlain, "plain"},
|
||||
{DCMMACed, "mac"},
|
||||
{DCMEncrypted, "encrypt"},
|
||||
};
|
||||
|
||||
int commmode = DCMPlain;
|
||||
CLIGetOptionListWithReturn(ctx, 8, cmode_opts, ARRAY_LENGTH(cmode_opts), &commmode);
|
||||
PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(cmode_opts, ARRAY_LENGTH(cmode_opts), commmode));
|
||||
|
||||
const CLIParserOption commc_opts[] = {
|
||||
{DCCNative, "native"},
|
||||
{DCCNativeISO, "niso"},
|
||||
{DCCISO, "iso"},
|
||||
};
|
||||
|
||||
int commchann = DCCNativeISO;
|
||||
CLIGetOptionListWithReturn(ctx, 9, commc_opts, ARRAY_LENGTH(commc_opts), &commchann);
|
||||
PrintAndLogEx(INFO, "comm mode: %s", CLIGetOptionListStr(commc_opts, ARRAY_LENGTH(commc_opts), commchann));
|
||||
|
||||
const CLIParserOption authc_opts[] = {
|
||||
{DACd40, "d40"},
|
||||
{DACEV1, "ev1"},
|
||||
{DACEV2, "ev2"},
|
||||
};
|
||||
|
||||
int authchann = DACEV1;
|
||||
CLIGetOptionListWithReturn(ctx, 10, authc_opts, ARRAY_LENGTH(authc_opts), &authchann);
|
||||
PrintAndLogEx(INFO, "auth channel: %s", CLIGetOptionListStr(authc_opts, ARRAY_LENGTH(authc_opts), authchann));
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
DesfireContext dctx;
|
||||
DesfireSetKey(&dctx, keyNum, ares, key);
|
||||
DesfireSetCommandChannel(&dctx, commchann);
|
||||
int securechann = defaultSecureChannel;
|
||||
int res = CmdDesGetSessionParameters(ctx, &dctx, 3, 4, 5, 6, 7, 8, 9, 10, &securechann);
|
||||
if (res) {
|
||||
CLIParserFree(ctx);
|
||||
return res;
|
||||
}
|
||||
|
||||
SetAPDULogging(APDULogging);
|
||||
CLIParserFree(ctx);
|
||||
|
||||
int res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
|
||||
if (verbose)
|
||||
DesfirePrintContext(&dctx);
|
||||
|
||||
res = DesfireSelectAIDHex(&dctx, 0x000000, false, 0);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Desfire select " _RED_("error") ".");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
res = DesfireAuthenticate(&dctx, authchann);
|
||||
res = DesfireAuthenticate(&dctx, securechann);
|
||||
if (res != PM3_SUCCESS) {
|
||||
PrintAndLogEx(ERR, "Desfire authenticate " _RED_("error") ". Result: %d", res);
|
||||
DropField();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Iceman, 2014
|
||||
// Copyright (C) Iceman, 2014
|
||||
// Copyright (C) 2021 Merlok
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*-
|
||||
* 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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,24 @@
|
|||
#ifndef __DESFIRE_CRYPTO_H
|
||||
/*-
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifndef __DESFIRE_CRYPTO_H
|
||||
#define __DESFIRE_CRYPTO_H
|
||||
|
||||
#include "common.h"
|
||||
|
|
@ -7,6 +27,7 @@
|
|||
|
||||
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// High frequency Desfire core functions
|
||||
//-----------------------------------------------------------------------------
|
||||
// Info from here and many other soursec from the internet
|
||||
// Info from here and many other sources from the public internet sites
|
||||
// https://github.com/revk/DESFireAES
|
||||
// https://github.com/step21/desfire_rfid
|
||||
// https://github.com/patsys/desfire-python/blob/master/Desfire/DESFire.py
|
||||
|
|
@ -163,8 +163,8 @@ void DesfireClearContext(DesfireContext *ctx) {
|
|||
ctx->keyType = T_DES;
|
||||
memset(ctx->key, 0, sizeof(ctx->key));
|
||||
|
||||
ctx->authChannel = DACNone;
|
||||
ctx->cmdChannel = DCCNative;
|
||||
ctx->secureChannel = DACNone;
|
||||
ctx->cmdSet = DCCNative;
|
||||
ctx->commMode = DCMNone;
|
||||
|
||||
ctx->kdfAlgo = 0;
|
||||
|
|
@ -175,7 +175,7 @@ void DesfireClearContext(DesfireContext *ctx) {
|
|||
}
|
||||
|
||||
void DesfireClearSession(DesfireContext *ctx) {
|
||||
ctx->authChannel = DACNone; // here none - not authenticared
|
||||
ctx->secureChannel = DACNone; // here none - not authenticared
|
||||
|
||||
memset(ctx->sessionKeyMAC, 0, sizeof(ctx->sessionKeyMAC));
|
||||
memset(ctx->sessionKeyEnc, 0, sizeof(ctx->sessionKeyEnc));
|
||||
|
|
@ -185,6 +185,11 @@ void DesfireClearSession(DesfireContext *ctx) {
|
|||
memset(ctx->TI, 0, sizeof(ctx->TI));
|
||||
}
|
||||
|
||||
void DesfirePrintContext(DesfireContext *ctx) {
|
||||
//PrintAndLogEx(INFO, "algo: %s", CLIGetOptionListStr(algo_opts, ARRAY_LENGTH(algo_opts), algores));
|
||||
PrintAndLogEx(INFO, "Key num: %d Key type: %d Key[%d]: %s", ctx->keyNum, ctx->keyType, key_size(ctx->keyType), sprint_hex(ctx->key, key_size(ctx->keyType)));
|
||||
}
|
||||
|
||||
void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key) {
|
||||
DesfireClearContext(ctx);
|
||||
|
||||
|
|
@ -193,8 +198,19 @@ void DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO
|
|||
memcpy(ctx->key, key, desfire_get_key_length(keyType));
|
||||
}
|
||||
|
||||
void DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel) {
|
||||
ctx->cmdChannel = cmdChannel;
|
||||
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) {
|
||||
|
|
@ -342,7 +358,7 @@ static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t
|
|||
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) {
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
switch(ctx->cmdChannel) {
|
||||
switch(ctx->cmdSet) {
|
||||
case DCCNative:
|
||||
res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, respcode, resp, resplen, enable_chaining, splitbysize);
|
||||
break;
|
||||
|
|
@ -397,17 +413,17 @@ int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uin
|
|||
}
|
||||
|
||||
bool DesfireIsAuthenticated(DesfireContext *dctx) {
|
||||
return dctx->authChannel != DACNone;
|
||||
return dctx->secureChannel != DACNone;
|
||||
}
|
||||
|
||||
int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) {
|
||||
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
|
||||
// 3 different communication modes, PLAIN,MAC,CRYPTO
|
||||
|
||||
DesfireClearSession(dctx);
|
||||
|
||||
if (authChannel == DACNone)
|
||||
if (secureChannel == DACNone)
|
||||
return PM3_SUCCESS;
|
||||
|
||||
mbedtls_aes_context ctx;
|
||||
|
|
@ -456,8 +472,8 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) {
|
|||
}
|
||||
|
||||
uint8_t subcommand = MFDES_AUTHENTICATE;
|
||||
dctx->authChannel = authChannel;
|
||||
if (dctx->authChannel == DACEV1) {
|
||||
dctx->secureChannel = secureChannel;
|
||||
if (dctx->secureChannel == DACEV1) {
|
||||
if (dctx->keyType == T_AES)
|
||||
subcommand = MFDES_AUTHENTICATE_AES;
|
||||
else
|
||||
|
|
@ -522,7 +538,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) {
|
|||
uint8_t encRndA[16] = {0x00};
|
||||
|
||||
// - Encrypt our response
|
||||
if (dctx->authChannel == DACd40) {
|
||||
if (dctx->secureChannel == DACd40) {
|
||||
des_decrypt(encRndA, RndA, key->data);
|
||||
memcpy(both, encRndA, rndlen);
|
||||
|
||||
|
|
@ -532,7 +548,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) {
|
|||
|
||||
des_decrypt(encRndB, rotRndB, key->data);
|
||||
memcpy(both + rndlen, encRndB, rndlen);
|
||||
} else if (dctx->authChannel == DACEV1 && dctx->keyType != T_AES) {
|
||||
} else if (dctx->secureChannel == DACEV1 && dctx->keyType != T_AES) {
|
||||
if (dctx->keyType == T_3DES) {
|
||||
uint8_t tmp[16] = {0x00};
|
||||
memcpy(tmp, RndA, rndlen);
|
||||
|
|
@ -558,7 +574,7 @@ int DesfireAuthenticate(DesfireContext *dctx, DesfireAuthChannel authChannel) {
|
|||
PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32));
|
||||
}
|
||||
}
|
||||
} else if (dctx->authChannel == DACEV1 && dctx->keyType == T_AES) {
|
||||
} else if (dctx->secureChannel == DACEV1 && dctx->keyType == T_AES) {
|
||||
uint8_t tmp[32] = {0x00};
|
||||
memcpy(tmp, RndA, rndlen);
|
||||
memcpy(tmp + rndlen, rotRndB, rndlen);
|
||||
|
|
@ -637,7 +653,7 @@ PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen));
|
|||
memcpy(&dctx->sessionKeyEnc[8], dctx->sessionKeyEnc, 8);
|
||||
}
|
||||
|
||||
if (dctx->authChannel == DACEV1) {
|
||||
if (dctx->secureChannel == DACEV1) {
|
||||
cmac_generate_subkeys(&sesskey, MCD_RECEIVE);
|
||||
//key->cmac_sk1 and key->cmac_sk2
|
||||
//memcpy(dctx->sessionKeyEnc, sesskey.data, desfire_get_key_length(dctx->keyType));
|
||||
|
|
|
|||
|
|
@ -28,13 +28,13 @@ typedef enum {
|
|||
DACd40,
|
||||
DACEV1,
|
||||
DACEV2
|
||||
} DesfireAuthChannel;
|
||||
} DesfireSecureChannel;
|
||||
|
||||
typedef enum {
|
||||
DCCNative,
|
||||
DCCNativeISO,
|
||||
DCCISO
|
||||
} DesfireCommandChannel;
|
||||
} DesfireCommandSet;
|
||||
|
||||
typedef enum {
|
||||
DCMNone,
|
||||
|
|
@ -54,9 +54,9 @@ typedef struct DesfireContextS {
|
|||
uint8_t kdfInputLen;
|
||||
uint8_t kdfInput[31];
|
||||
|
||||
DesfireAuthChannel authChannel; // none/d40/ev1/ev2
|
||||
DesfireCommandChannel cmdChannel; // native/nativeiso/iso
|
||||
DesfireCommunicationMode commMode; // plain/mac/enc
|
||||
DesfireSecureChannel secureChannel; // none/d40/ev1/ev2
|
||||
DesfireCommandSet cmdSet; // native/nativeiso/iso
|
||||
DesfireCommunicationMode commMode; // plain/mac/enc
|
||||
|
||||
uint8_t sessionKeyMAC[DESF_MAX_KEY_LEN];
|
||||
uint8_t sessionKeyEnc[DESF_MAX_KEY_LEN]; // look at mifare4.h - mf4Session_t
|
||||
|
|
@ -68,9 +68,12 @@ typedef struct DesfireContextS {
|
|||
} DesfireContext;
|
||||
|
||||
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 DesfireSetCommandChannel(DesfireContext *ctx, DesfireCommandChannel cmdChannel);
|
||||
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);
|
||||
|
|
@ -82,7 +85,7 @@ int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uin
|
|||
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, DesfireAuthChannel authChannel);
|
||||
int DesfireAuthenticate(DesfireContext *dctx, DesfireSecureChannel secureChannel);
|
||||
bool DesfireIsAuthenticated(DesfireContext *dctx);
|
||||
|
||||
int DesfireGetAIDList(DesfireContext *dctx, uint8_t *resp, size_t *resplen);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue