mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 18:48:13 -07:00
desfire channel sketch
This commit is contained in:
parent
bf1212f63e
commit
2fa6c4643e
8 changed files with 444 additions and 0 deletions
|
@ -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/desfirecore.c
|
||||
${PM3_ROOT}/client/src/uart/uart_posix.c
|
||||
${PM3_ROOT}/client/src/uart/uart_win32.c
|
||||
${PM3_ROOT}/client/src/ui/overlays.ui
|
||||
|
|
|
@ -572,6 +572,7 @@ SRCS = aiddesfire.c \
|
|||
loclass/elite_crack.c \
|
||||
loclass/ikeys.c \
|
||||
mifare/desfire_crypto.c \
|
||||
mifare/desfirecore.c \
|
||||
mifare/mad.c \
|
||||
mifare/mfkey.c \
|
||||
mifare/mifare4.c \
|
||||
|
|
|
@ -5116,6 +5116,121 @@ static int CmdHF14aDesMAD(const char *Cmd) {
|
|||
}
|
||||
*/
|
||||
|
||||
static int CmdHF14ADesGetAIDs(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "hf mfdes getaids",
|
||||
"Get Application IDs list from card. Master key needs to be provided.",
|
||||
"hf mfdes getaids -n 0 -t des -k 0000000000000000 -f none -> execute with default factory setup");
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_lit0("a", "apdu", "show APDU requests and responses"),
|
||||
arg_lit0("v", "verbose", "show technical data"),
|
||||
arg_int0("n", "keyno", "<keyno>", "Key number"),
|
||||
arg_int0("t", "algo", "<algo>", "Crypt algo: DES, 2TDEA, 3TDEA, AES"),
|
||||
arg_str0("k", "key", "<Key>", "Key for authenticate (HEX 8(DES), 16(2TDEA or AES) or 24(3TDEA) bytes)"),
|
||||
arg_int0("f", "kdf", "<kdf>", "Key Derivation Function (KDF): None(default), AN10922, Gallagher"),
|
||||
arg_str0("i", "kdfi", "<kdfi>", "KDF input (HEX 1-31 bytes)"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
|
||||
/*
|
||||
int aidlength = 0;
|
||||
uint8_t aid[3] = {0};
|
||||
CLIGetHexWithReturn(ctx, 1, aid, &aidlength);
|
||||
swap24(aid);
|
||||
uint8_t vkey[16] = {0};
|
||||
int vkeylen = 0;
|
||||
CLIGetHexWithReturn(ctx, 2, vkey, &vkeylen);
|
||||
|
||||
if (vkeylen > 0) {
|
||||
if (vkeylen == 8) {
|
||||
memcpy(&deskeyList[deskeyListLen], vkey, 8);
|
||||
deskeyListLen++;
|
||||
} else if (vkeylen == 16) {
|
||||
memcpy(&aeskeyList[aeskeyListLen], vkey, 16);
|
||||
aeskeyListLen++;
|
||||
} else if (vkeylen == 24) {
|
||||
memcpy(&k3kkeyList[k3kkeyListLen], vkey, 16);
|
||||
k3kkeyListLen++;
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Specified key must have 8, 16 or 24 bytes length.");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dict_filename[FILE_PATH_SIZE + 2] = {0};
|
||||
int dict_filenamelen = 0;
|
||||
if (CLIParamStrToBuf(arg_get_str(ctx, 3), dict_filename, FILE_PATH_SIZE, &dict_filenamelen)) {
|
||||
PrintAndLogEx(FAILED, "File name too long or invalid.");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
bool pattern1b = arg_get_lit(ctx, 4);
|
||||
bool pattern2b = arg_get_lit(ctx, 5);
|
||||
|
||||
if (pattern1b && pattern2b) {
|
||||
PrintAndLogEx(ERR, "Pattern search mode must be 2-byte or 1-byte only.");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (dict_filenamelen && (pattern1b || pattern2b)) {
|
||||
PrintAndLogEx(ERR, "Pattern search mode and dictionary mode can't be used in one command.");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint32_t startPattern = 0x0000;
|
||||
uint8_t vpattern[2];
|
||||
int vpatternlen = 0;
|
||||
CLIGetHexWithReturn(ctx, 6, vpattern, &vpatternlen);
|
||||
if (vpatternlen > 0) {
|
||||
if (vpatternlen <= 2) {
|
||||
startPattern = (vpattern[0] << 8) + vpattern[1];
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Pattern must be 2-byte length.");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
if (!pattern2b)
|
||||
PrintAndLogEx(WARNING, "Pattern entered, but search mode not is 2-byte search.");
|
||||
}
|
||||
|
||||
uint8_t jsonname[250] = {0};
|
||||
int jsonnamelen = 0;
|
||||
if (CLIParamStrToBuf(arg_get_str(ctx, 7), jsonname, sizeof(jsonname), &jsonnamelen)) {
|
||||
PrintAndLogEx(ERR, "Invalid json name.");
|
||||
CLIParserFree(ctx);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
jsonname[jsonnamelen] = 0;
|
||||
|
||||
bool verbose = arg_get_lit(ctx, 8);
|
||||
|
||||
// Get KDF input
|
||||
uint8_t kdfInput[31] = {0};
|
||||
int kdfInputLen = 0;
|
||||
uint8_t cmdKDFAlgo = arg_get_int_def(ctx, 9, 0);
|
||||
CLIGetHexWithReturn(ctx, 10, kdfInput, &kdfInputLen);
|
||||
*/
|
||||
CLIParserFree(ctx);
|
||||
|
||||
|
||||
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// {"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"},
|
||||
static int CmdHF14ADesGetAppNames(const char *Cmd) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "---------------------- " _CYAN_("general") " ----------------------"},
|
||||
|
@ -5134,6 +5249,8 @@ static command_t CommandTable[] = {
|
|||
{"createaid", CmdHF14ADesCreateApp, IfPm3Iso14443a, "Create Application ID"},
|
||||
{"deleteaid", CmdHF14ADesDeleteApp, IfPm3Iso14443a, "Delete Application ID"},
|
||||
{"selectaid", CmdHF14ADesSelectApp, IfPm3Iso14443a, "Select Application ID"},
|
||||
{"getaids", CmdHF14ADesGetAIDs, IfPm3Iso14443a, "Get Application IDs list"},
|
||||
{"getappnames", CmdHF14ADesGetAppNames, IfPm3Iso14443a, "Get Applications list"},
|
||||
{"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("Files") " -----------------------"},
|
||||
{"changevalue", CmdHF14ADesChangeValue, IfPm3Iso14443a, "Write value of a value file (credit/debit/clear)"},
|
||||
{"clearfile", CmdHF14ADesClearRecordFile, IfPm3Iso14443a, "Clear record File"},
|
||||
|
|
|
@ -51,6 +51,17 @@ static inline void update_key_schedules(desfirekey_t key) {
|
|||
// }
|
||||
}
|
||||
|
||||
int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type) {
|
||||
switch (key_type) {
|
||||
case T_DES: return 8;
|
||||
case T_3DES: return 16;
|
||||
case T_3K3DES: return 24;
|
||||
case T_AES: return 16;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
void des_encrypt(void *out, const void *in, const void *key) {
|
||||
|
|
|
@ -60,6 +60,8 @@ enum DESFIRE_CRYPTOALGO {
|
|||
T_AES = 0x03
|
||||
};
|
||||
|
||||
int desfire_get_key_length(enum DESFIRE_CRYPTOALGO key_type);
|
||||
|
||||
enum DESFIRE_AUTH_SCHEME {
|
||||
AS_LEGACY,
|
||||
AS_NEW
|
||||
|
|
236
client/src/mifare/desfirecore.c
Normal file
236
client/src/mifare/desfirecore.c
Normal file
|
@ -0,0 +1,236 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 Romain Tartiere.
|
||||
// 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
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// High frequency Desfire core functions
|
||||
//-----------------------------------------------------------------------------
|
||||
// Info from here and many other soursec from the internet
|
||||
// https://github.com/revk/DESFireAES
|
||||
// https://github.com/step21/desfire_rfid
|
||||
// https://github.com/patsys/desfire-python/blob/master/Desfire/DESFire.py
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "desfirecore.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <util.h>
|
||||
#include "ui.h"
|
||||
#include "protocols.h"
|
||||
#include "cmdhf14a.h"
|
||||
#include "iso7816/apduinfo.h" // APDU manipulation / errorcodes
|
||||
#include "iso7816/iso7816core.h" // APDU logging
|
||||
#include "util_posix.h" // msleep
|
||||
#include "mifare/desfire_crypto.h"
|
||||
|
||||
void DesfireClearContext(DesfireContext *ctx) {
|
||||
ctx->keyNum = 0;
|
||||
ctx->keyType = T_DES;
|
||||
memset(ctx->key, 0, sizeof(ctx->key));
|
||||
|
||||
ctx->authChannel = DACNone;
|
||||
ctx->cmdChannel = DCCNative;
|
||||
ctx->commMode = DCMNone;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
uint16_t isw = 0;
|
||||
int res = 0;
|
||||
|
||||
if (activate_field) {
|
||||
DropField();
|
||||
msleep(50);
|
||||
}
|
||||
|
||||
uint8_t data[APDU_RES_LEN] = {0};
|
||||
|
||||
// COMPUTE APDU
|
||||
int datalen = 0;
|
||||
if (APDUEncodeS(&apdu, false, 0x100, data, &datalen)) { // 100 == with Le
|
||||
PrintAndLogEx(ERR, "APDU encoding error.");
|
||||
return PM3_EAPDU_ENCODEFAIL;
|
||||
}
|
||||
|
||||
if (GetAPDULogging())
|
||||
PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, datalen));
|
||||
|
||||
res = ExchangeAPDU14a(data, datalen, activate_field, true, result, max_result_len, (int *)result_len);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (GetAPDULogging())
|
||||
PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len));
|
||||
|
||||
if (*result_len < 2) {
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
*result_len -= 2;
|
||||
isw = (result[*result_len] << 8) + result[*result_len + 1];
|
||||
if (sw)
|
||||
*sw = isw;
|
||||
|
||||
if (isw != 0x9000 &&
|
||||
isw != DESFIRE_GET_ISO_STATUS(MFDES_S_OPERATION_OK) &&
|
||||
isw != DESFIRE_GET_ISO_STATUS(MFDES_S_SIGNATURE) &&
|
||||
isw != DESFIRE_GET_ISO_STATUS(MFDES_S_ADDITIONAL_FRAME) &&
|
||||
isw != DESFIRE_GET_ISO_STATUS(MFDES_S_NO_CHANGES)) {
|
||||
if (GetAPDULogging()) {
|
||||
if (isw >> 8 == 0x61) {
|
||||
PrintAndLogEx(ERR, "APDU chaining len: 0x%02x -->", isw & 0xff);
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [0x%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(isw >> 8, isw & 0xff));
|
||||
return PM3_EAPDU_FAIL;
|
||||
}
|
||||
}
|
||||
return PM3_EAPDU_FAIL;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int DesfireExchangeNative(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) {
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int DesfireExchangeISO(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) {
|
||||
if (resplen)
|
||||
*resplen = 0;
|
||||
|
||||
// TODO !!!
|
||||
size_t splitbysize = 0;
|
||||
|
||||
uint16_t sw = 0;
|
||||
uint8_t buf[255 * 5] = {0x00};
|
||||
uint32_t buflen = 0;
|
||||
uint32_t pos = 0;
|
||||
uint32_t i = 1;
|
||||
|
||||
sAPDU apdu = {0};
|
||||
apdu.CLA = MFDES_NATIVE_ISO7816_WRAP_CLA; //0x90
|
||||
apdu.INS = cmd;
|
||||
apdu.Lc = datalen;
|
||||
apdu.P1 = 0;
|
||||
apdu.P2 = 0;
|
||||
apdu.data = data;
|
||||
|
||||
int res = DESFIRESendApdu(activate_field, apdu, buf, sizeof(buf), &buflen, &sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
//PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw));
|
||||
return res;
|
||||
}
|
||||
if (resp)
|
||||
memcpy(resp, buf, buflen);
|
||||
|
||||
pos += buflen;
|
||||
if (!enable_chaining) {
|
||||
if (sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) {
|
||||
if (resplen)
|
||||
*resplen = pos;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
while (sw == DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) {
|
||||
apdu.CLA = MFDES_NATIVE_ISO7816_WRAP_CLA; //0x90
|
||||
apdu.INS = MFDES_ADDITIONAL_FRAME; //0xAF
|
||||
apdu.Lc = 0;
|
||||
apdu.P1 = 0;
|
||||
apdu.P2 = 0;
|
||||
apdu.data = NULL;
|
||||
|
||||
res = DESFIRESendApdu(false, apdu, buf, sizeof(buf), &buflen, &sw);
|
||||
if (res != PM3_SUCCESS) {
|
||||
//PrintAndLogEx(DEBUG, "error DESFIRESendApdu %s", GetErrorString(res, &sw));
|
||||
return res;
|
||||
}
|
||||
|
||||
if (resp != NULL) {
|
||||
if (splitbysize) {
|
||||
memcpy(&resp[i * splitbysize], buf, buflen);
|
||||
i += 1;
|
||||
} else {
|
||||
memcpy(&resp[pos], buf, buflen);
|
||||
}
|
||||
}
|
||||
pos += buflen;
|
||||
|
||||
if (sw != DESFIRE_GET_ISO_STATUS(MFDES_ADDITIONAL_FRAME)) break;
|
||||
}
|
||||
|
||||
if (resplen)
|
||||
*resplen = (splitbysize) ? i : pos;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining) {
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
switch(ctx->cmdChannel) {
|
||||
case DCCNative:
|
||||
res = DesfireExchangeNative(activate_field, ctx, cmd, data, datalen, resp, resplen, enable_chaining);
|
||||
break;
|
||||
case DCCNativeISO:
|
||||
res = DesfireExchangeISO(activate_field, ctx, cmd, data, datalen, resp, resplen, enable_chaining);
|
||||
break;
|
||||
case DCCISO:
|
||||
return PM3_EAPDU_FAIL;
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen) {
|
||||
return DesfireExchangeEx(false, ctx, cmd, data, datalen, resp, resplen, true);
|
||||
}
|
||||
|
||||
int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2) {
|
||||
if (aid1 == NULL)
|
||||
return PM3_EINVARG;
|
||||
|
||||
uint8_t data[6] = {0};
|
||||
memcpy(data, aid1, 3);
|
||||
if (aid2 != NULL)
|
||||
memcpy(&data[3], aid2, 3);
|
||||
uint8_t resp[257] = {0};
|
||||
size_t resplen = 0;
|
||||
int res = DesfireExchangeEx(true, ctx, MFDES_SELECT_APPLICATION, data, (aid2 == NULL) ? 3 : 6, resp, &resplen, true);
|
||||
if (res == PM3_SUCCESS && resplen != 0)
|
||||
return PM3_ECARDEXCHANGE;
|
||||
return res;
|
||||
}
|
||||
|
||||
int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2) {
|
||||
uint8_t data[6] = {0};
|
||||
// TODO !!!!
|
||||
data[0] = aid1 & 0xff;
|
||||
data[1] = (aid1 >> 8) & 0xff;
|
||||
data[2] = (aid1 >> 16) & 0xff;
|
||||
return DesfireSelectAID(ctx, data, (select_two) ? &data[3] : NULL);
|
||||
}
|
||||
|
75
client/src/mifare/desfirecore.h
Normal file
75
client/src/mifare/desfirecore.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2010 Romain Tartiere.
|
||||
// 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
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// High frequency Desfire core functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __DESFIRECORE_H
|
||||
#define __DESFIRECORE_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 {
|
||||
DACNone,
|
||||
DACd40,
|
||||
DACEV1,
|
||||
DACEV2
|
||||
} DesfireAuthChannel;
|
||||
|
||||
typedef enum {
|
||||
DCCNative,
|
||||
DCCNativeISO,
|
||||
DCCISO
|
||||
} DesfireCommandChannel;
|
||||
|
||||
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
|
||||
// KDF input
|
||||
|
||||
DesfireAuthChannel authChannel; // none/d40/ev1/ev2
|
||||
DesfireCommandChannel cmdChannel; // 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
|
||||
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 DesfireSetKey(DesfireContext *ctx, uint8_t keyNum, enum DESFIRE_CRYPTOALGO keyType, uint8_t *key);
|
||||
|
||||
int DesfireSelectAID(DesfireContext *ctx, uint8_t *aid1, uint8_t *aid2);
|
||||
int DesfireSelectAIDHex(DesfireContext *ctx, uint32_t aid1, bool select_two, uint32_t aid2);
|
||||
int DesfireExchange(DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen);
|
||||
int DesfireExchangeEx(bool activate_field, DesfireContext *ctx, uint8_t cmd, uint8_t *data, size_t datalen, uint8_t *resp, size_t *resplen, bool enable_chaining);
|
||||
|
||||
|
||||
#endif // __DESFIRECORE_H
|
|
@ -459,6 +459,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define MFDES_GET_FILE_SETTINGS 0xF5
|
||||
#define MFDES_FORMAT_PICC 0xFC
|
||||
#define MFDES_VERIFY_PC 0xFD
|
||||
#define MFDES_NATIVE_ISO7816_WRAP_CLA 0x90
|
||||
|
||||
// MIFARE DESFire status & error codes:
|
||||
#define MFDES_S_OPERATION_OK 0x00
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue